简体   繁体   English

从DataTable创建数据透视表

[英]Create a Pivot Table from a DataTable

I am using C# winforms to create an application that needs to turn a datatable into a pivot table. 我正在使用C#winforms创建一个需要将数据表转换为数据透视表的应用程序。 I have the pivot table working fine from a SQL end, but creating it from a datatable seems trickier. 我让数据透视表从SQL端运行良好,但从数据表创建它似乎比较棘手。 I couldn't seem to find anything built into .NET for this. 我似乎无法在.NET中找到任何内置的东西。

NOTE: I do have to do this from a .NET side as I manipulate the data prior to creating the pivot. 注意:我必须在.NET端执行此操作,因为我在创建数据透视之前操作数据。

I've read through some articles that did some similar things as this, but I've had difficultly applying them to my problem. 我读过一些做过类似事情的文章,但我很难将它们应用到我的问题中。

*I have a datatable with the columns "StartDateTime", "Tap", and "Data". *我有一个数据表,其中包含“StartDateTime”,“Tap”和“Data”列。 The startdates should be grouped together and data values averaged (sometimes more than one data value per startdate). 应将startdates组合在一起并平均数据值(有时每个startdate有多个数据值)。 The table is shown below: 表格如下所示:

在此输入图像描述

Pivot table should output like the image below (not rounded values though). 数据透视表应该输出如下图所示(尽管不是舍入值)。 The column numbers are the distinct tap numbers (one for each unique one). 列号是不同的抽头编号(每个唯一编号一个)。

数据透视表

How can I go about creating this pivot table from the datatable? 如何从数据表创建此数据透视表?

EDIT: forgot to mention, these tap values are not always from 1-4, they do vary in number and value. 编辑:忘了提,这些抽头值并不总是从1-4开始,它们的数量和价值各不相同。

Learn the hash-pivot tesuji: 学习hash-pivot tesuji:

var inDT = new DataTable();
// Fill the input table

var oDT = new DataTable();
var dfq = new Dictionary<DateTime, DataRow>;
oDT.Columns.Add("StartDateTime", typeof(DateTime));
for (int i = 0; i < inDT.Rows.Count; i++) {
    var key = (DateTime)inDT.Rows[i][0];
    var row = (String)inDT.Rows[i][2];
    var data = (Double)inDT.Rows[i][1];

    if (!oDT.Columns.Contains(row)) {
       oDT.Columns.Add(row);
    }
    if (dfq.ContainsKey(key)) {
        dfq[key][row] = data;
    } else {
        var oRow = oDT.NewRow();
        oRow[0] = key;
        oRow[row] = data;
        dfq.Add(key, oRow);
        oDT.Rows.Add(oRow);
    }
}
// pivot table in oDT

Pivot table like that can be easily calculated with free NReco.PivotData aggregation library: 像这样的数据透视表可以使用免费的NReco.PivotData聚合库轻松计算:

DataTable t;  // assume it has: StartDateTime, Data, Tap
var pivotData = new PivotData(
    new string[] {"StartDateTime","Tap"},
    new AverageAggregatorFactory("Data"),
    new DataTableReader(t) );
var pvtTbl = new PivotTable(
    new [] {"StartDateTime"},  // row dimension(s)
    new [] {"Tap"}, // column dimension(s),
    pivotData);

Row and column keys are represented by pvtTbl.RowKeys and pvtTbl.ColumnKeys collections; 行键和列键由pvtTbl.RowKeys和pvtTbl.ColumnKeys集合表示; values / totals could be accessed by indexer (for example: pvtTbl[0,0].Value ) or by row+column key (for example: pivotData[new Key(new DateTime(2012, 3, 30, 11, 42, 00)), new Key(4)].Value ). 值/总数可以由索引器(例如: pvtTbl[0,0].Value )或行+列键访问(例如: pivotData[new Key(new DateTime(2012, 3, 30, 11, 42, 00)), new Key(4)].Value )。

Another small piece of code to pivot any table you would want: 另一小段代码可以转动您想要的任何表格:

        var dataTable = new DataTable(); // your input DataTable here!
        var pivotedDataTable = new DataTable(); //the pivoted result
        var firstColumnName = "Year";
        var pivotColumnName = "Codes";

        pivotedDataTable.Columns.Add(firstColumnName);

        pivotedDataTable.Columns.AddRange(
            dataTable.Rows.Cast<DataRow>().Select(x => new DataColumn(x[pivotColumnName].ToString())).ToArray());

        for (var index = 1; index < dataTable.Columns.Count; index++)
        {
            pivotedDataTable.Rows.Add(
                new List<object> { dataTable.Columns[index].ColumnName }.Concat(
                    dataTable.Rows.Cast<DataRow>().Select(x => x[dataTable.Columns[index].ColumnName])).ToArray());
        }

Maybe this will help you. 也许这会对你有所帮助。 It is in vb.net. 它在vb.net中。

Public Function pivot_datatable(ByVal datatable_source As DataTable, ByVal datacolumn_rows As DataColumn(), ByVal datacolumn_columns As DataColumn, ByVal datacolumn_value As DataColumn) As DataTable
    Dim temp_datacolumn As DataColumn
    Dim current_datarow As DataRow
    Dim datarow_destination As DataRow = Nothing
    Dim current_column_name As String = ""
    Dim primary_key() As DataColumn = New DataColumn() {}
    Dim key_columns() As Object
    Dim newOrdinal As Integer
    Dim i As Integer
    Dim sort_string As String = ""

    Try
        pivot_datatable = New DataTable()

        For Each temp_datacolumn In datatable_source.Columns
            If temp_datacolumn.Ordinal <> datacolumn_columns.Ordinal AndAlso temp_datacolumn.Ordinal <> datacolumn_value.Ordinal Then
                array_insert(primary_key, pivot_datatable.Columns.Add(temp_datacolumn.ColumnName, temp_datacolumn.DataType))
                sort_string &= temp_datacolumn.ColumnName & " ASC, "
            End If
        Next
        pivot_datatable.PrimaryKey = primary_key

        For Each current_datarow In datatable_source.Rows ' Main Process to add values to pivot table
            current_column_name = current_datarow(datacolumn_columns.Ordinal).ToString
            If Not pivot_datatable.Columns.Contains(current_column_name) Then ' Column is new
                temp_datacolumn = pivot_datatable.Columns.Add(current_column_name, datacolumn_value.DataType)
                newOrdinal = temp_datacolumn.Ordinal
                For i = newOrdinal - 1 To datatable_source.Columns.Count - 2 Step -1
                    If temp_datacolumn.ColumnName.CompareTo(pivot_datatable.Columns(i).ColumnName) < 0 Then
                        newOrdinal = i
                    End If
                Next
                temp_datacolumn.SetOrdinal(newOrdinal)
            End If

            key_columns = New Object() {}
            For Each data_column As DataColumn In datacolumn_rows
                array_insert(key_columns, current_datarow(data_column.Ordinal).ToString)
            Next data_column
            datarow_destination = pivot_datatable.Rows.Find(key_columns)
            If datarow_destination Is Nothing Then ' New Row
                datarow_destination = pivot_datatable.NewRow()
                For Each temp_datacolumn In datatable_source.Columns
                    If temp_datacolumn.Ordinal <> datacolumn_columns.Ordinal AndAlso temp_datacolumn.Ordinal <> datacolumn_value.Ordinal Then
                        datarow_destination(temp_datacolumn.ColumnName) = current_datarow(temp_datacolumn.ColumnName)
                    End If
                Next
                pivot_datatable.Rows.Add(datarow_destination)
            End If
            datarow_destination(current_column_name) = current_datarow(datacolumn_value.Ordinal)
        Next

        Return sort_datatable(pivot_datatable, sort_string.Substring(0, sort_string.Length - 2))
    Catch ex As Exception
        Return Nothing
    End Try
End Function

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM