从DataTable创建数据透视表

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

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

我读过一些做过类似事情的文章,但我很难将它们应用到我的问题中。

*我有一个数据表,其中包含“StartDateTime”,“Tap”和“Data”列。 应将startdates组合在一起并平均数据值(有时每个startdate有多个数据值)。 表格如下所示:

在此处输入图像描述

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

数据透视表

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

编辑:忘了提,这些抽头值并不总是从1-4开始,它们的数量和价值各不相同。

学习hash-pivot tesuji:

var oDT = new DataTable; var dfq = new Dictionary; 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); } } 

像这样的数据透视表可以使用免费的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 )。

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

  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().Select(x => new DataColumn(x[pivotColumnName].ToString())).ToArray()); for (var index = 1; index < dataTable.Columns.Count; index++) { pivotedDataTable.Rows.Add( new List { dataTable.Columns[index].ColumnName }.Concat( dataTable.Rows.Cast().Select(x => x[dataTable.Columns[index].ColumnName])).ToArray()); } 

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