【问题标题】:Create a Pivot Table from a DataTable从数据表创建数据透视表
【发布时间】:2012-04-16 09:22:00
【问题描述】:

我正在使用 C# winforms 创建一个需要将数据表转换为数据透视表的应用程序。我的数据透视表从 SQL 端工作正常,但从数据表创建它似乎更棘手。我似乎找不到任何内置在.NET中的东西。

注意:我必须从 .NET 端执行此操作,因为我在创建数据透视之前操作数据。

我已经阅读了一些与此类似的文章,但我很难将它们应用于我的问题。

*我有一个包含“StartDateTime”、“Tap”和“Data”列的数据表。应将开始日期分组在一起并对数据值进行平均(有时每个开始日期不止一个数据值)。下表如下:

数据透视表的输出应如下图所示(但不是四舍五入的值)。列号是不同的抽头号(每个唯一的抽头号一个)。

如何从数据表创建此数据透视表?

编辑:忘了提一下,这些抽头值并不总是从 1 到 4,它们的数量和值确实不同。

【问题讨论】:

标签: c# winforms datatable pivot pivot-table


【解决方案1】:

学习哈希轴手筋:

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

【讨论】:

  • 如果您添加一些评论以了解这里发生的事情,那就太好了
  • 该行作为参考添加到字典中。所以在创建行并添加到字典后,通过字典中的行将数据添加到DataTable中。
【解决方案2】:

另外一小段代码可以旋转您想要的任何表格:

        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());
        }

【讨论】:

    【解决方案3】:

    可以使用免费的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);
    

    行和列键由 pvtTbl.RowKeys 和 pvtTbl.ColumnKeys 集合表示;值/总计可以通过索引器(例如:pvtTbl[0,0].Value)或行+列键(例如:pivotData[new Key(new DateTime(2012, 3, 30, 11, 42, 00)), new Key(4)].Value)访问。

    【讨论】:

    • 我很确定他是在问如何自己做而不是使用图书馆。图书馆很好,但不是答案。
    【解决方案4】:

    也许这会对你有所帮助。它在 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
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-06-20
      • 2014-08-14
      • 1970-01-01
      • 2022-01-03
      • 2018-03-29
      相关资源
      最近更新 更多