2012-04-02 4 views
11

Ich verwende C# winforms, um eine Anwendung zu erstellen, die eine Datentabelle in eine Pivot-Tabelle umwandeln muss. Ich habe die Pivot-Tabelle funktioniert gut von einem SQL-Ende, aber es aus einer Datentabelle erstellen scheint kniffliger. Ich konnte anscheinend nichts in .NET eingebaut finden.Erstellen Sie eine Pivot-Tabelle aus einer DataTable

HINWEIS: Ich muss dies von einer .NET-Seite tun, wie ich die Daten vor dem Erstellen des Pivot manipulieren.

Ich habe einige Artikel gelesen, die ähnliche Dinge wie dieses gemacht haben, aber ich habe sie schwer auf mein Problem angewendet.

* Ich habe eine Datentabelle mit den Spalten "StartDateTime", "Tap" und "Data". Die Startdaten sollten gruppiert und die Datenwerte gemittelt werden (manchmal mehr als ein Datenwert pro Startdatum). Die Tabelle ist unten gezeigt:

enter image description here

Pivot Tabellenausgabe sollte wie das Bild unten (nicht Werte gerundet obwohl). Die Spaltennummern sind die eindeutigen Abgriffnummern (eine für jede eindeutige).

Pivot Table

Wie kann ich mich über diese Pivot-Tabelle aus der Datentabelle zu erstellen?

EDIT: vergessen zu erwähnen, diese Tap-Werte sind nicht immer von 1-4, sie variieren in Anzahl und Wert.

+8

Würde diese Arbeit: http://www.codeproject.com/Articles/46486/Pivoting-DataTable-Simplified – mellamokb

+1

die ganze Spent Morgen herumblödeln und es nicht funktionieren lassen - danke, dass du mich überzeugt hast, es noch einmal zu versuchen! Funktioniert jetzt :) – ImGreg

+1

Es gibt ein Tutorial und eine schön eingepackte Klasse [hier] (http://www.codeproject.com/Articles/46486/Pivoting-DataTable-Simplified). –

Antwort

4

Lernen Sie die Hash-Pivot Tesuji:

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); 
    } 
} 
+1

es wäre toll, wenn Sie einen Kommentar hinzufügen, um zu verstehen, was hier passiert –

-1

diese Ihnen vielleicht helfen. Es ist in 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 
4

Pivot-Tabelle wie die leicht mit freier NReco.PivotData Aggregation Bibliothek berechnet werden:

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

Zeilen- und Spaltenschlüssel dargestellt wird durch pvtTbl.RowKeys und pvtTbl.ColumnKeys Sammlungen; Auf Werte/Gesamtsummen kann über den Indexer (z. B. pvtTbl[0,0].Value) oder über Zeile + Spaltenschlüssel (z. B. pivotData[new Key(new DateTime(2012, 3, 30, 11, 42, 00)), new Key(4)].Value) zugegriffen werden.

+1

Ich bin mir ziemlich sicher, dass er fragte, wie man es selbst macht und keine Bibliothek verwenden. Die Bibliothek ist sehr gut, aber nicht die Antwort. – Jon

0

Noch ein kleines Stück Code jeden Tisch schwenken würden Sie wollen:

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