2012-04-02 54 views
11

Estoy usando C# winforms para crear una aplicación que necesita convertir una tabla de datos en una tabla dinámica. Tengo la tabla dinámica funcionando bien desde un final de SQL, pero crearla desde una tabla de datos parece más complicado. No pude encontrar nada integrado en .NET para esto.Crear una tabla dinámica desde una DataTable

NOTA: Tengo que hacer esto desde un lado .NET mientras manipulo los datos antes de crear el pivote.

He leído algunos artículos que hacen cosas similares a esta, pero he tenido dificultades para aplicarlos a mi problema.

* Tengo una tabla de datos con las columnas "StartDateTime", "Tap" y "Data". Las fechas de inicio se deben agrupar y promediar los valores de los datos (a veces más de un valor de datos por fecha de inicio). La tabla se muestra a continuación:

enter image description here

Tabla pivote debe salida como la imagen de abajo (no redondeado valores aunque). Los números de columna son los distintos números de toque (uno para cada uno).

Pivot Table

¿Cómo puedo ir sobre la creación de esta tabla dinámica de la tabla de datos?

EDITAR: se olvidó de mencionar, estos valores de tap no son siempre de 1 a 4, varían en número y valor.

+8

Que este trabajo: http://www.codeproject.com/Articles/46486/Pivoting-DataTable-Simplified – mellamokb

+1

gastado la totalidad por la mañana, haciendo payasadas con él y no pude hacerlo funcionar, ¡gracias por convencerme de que intente de nuevo! Funciona ahora :) – ImGreg

+1

Hay un tutorial y una clase muy bien envuelta disponible [aquí] (http://www.codeproject.com/Articles/46486/Pivoting-DataTable-Simplified). –

Respuesta

4

aprender el tesuji de hash-pivote:

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

sería genial si agrega un comentario para entender lo que está pasando aquí –

-1

Tal vez esto le ayudará. Está en 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

Tabla pivote como que se puede calcular fácilmente con la biblioteca de NReco.PivotData agregación libre: teclas

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

de fila y de columna están representados por pvtTbl.RowKeys y colecciones pvtTbl.ColumnKeys; los valores/totales pueden ser accedidos por el indexador (por ejemplo: pvtTbl[0,0].Value) o por la fila + clave de columna (por ejemplo: pivotData[new Key(new DateTime(2012, 3, 30, 11, 42, 00)), new Key(4)].Value).

+1

Estoy bastante seguro de que estaba preguntando cómo hacerlo él mismo y no usar una biblioteca. La biblioteca es muy buena, pero no la respuesta. – Jon

0

Otra pequeña pieza de código para pivotar cualquier tabla que usted quiere:

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