2012-04-02 67 views
11

Tôi đang sử dụng C# winforms để tạo một ứng dụng cần phải chuyển đổi dữ liệu thành bảng tổng hợp. Tôi có bảng pivot làm việc tốt từ một kết thúc SQL, nhưng tạo ra nó từ một datatable có vẻ phức tạp hơn. Tôi dường như không thể tìm thấy bất cứ điều gì được xây dựng vào .NET cho việc này.Tạo một bảng tổng hợp từ một DataTable

LƯU Ý: Tôi phải thực hiện việc này từ phía .NET khi tôi thao tác dữ liệu trước khi tạo trục xoay.

Tôi đã đọc qua một số bài viết đã làm một số điều tương tự như thế này, nhưng tôi đã khó áp dụng chúng cho vấn đề của tôi.

* Tôi có dữ liệu với các cột "StartDateTime", "Tap" và "Data". Các startdate nên được nhóm lại với nhau và các giá trị dữ liệu được tính trung bình (đôi khi nhiều hơn một giá trị dữ liệu cho mỗi startdate). Bảng này được hiển thị dưới đây:

enter image description here

bảng Pivot nên đầu ra như hình dưới đây (không làm tròn giá trị mặc dù). Các số cột là các số hiệu riêng biệt (một cho mỗi số duy nhất).

Pivot Table

Làm thế nào tôi có thể đi về việc tạo bảng pivot này từ DataTable?

EDIT: quên đề cập, các giá trị nhấn này không phải lúc nào cũng từ 1-4, chúng thay đổi về số lượng và giá trị.

+8

công việc này có: http://www.codeproject.com/Articles/46486/Pivoting-DataTable-Simplified – mellamokb

+1

duyệt toàn bộ buổi sáng chú hề xung quanh với nó và không thể làm cho nó hoạt động - cảm ơn vì đã thuyết phục tôi thử lại! Hoạt động ngay bây giờ :) – ImGreg

+1

Có một hướng dẫn và một lớp học được gói gọn sẵn có tại đây (http://www.codeproject.com/Articles/46486/Pivoting-DataTable-Simplified). –

Trả lời

4

Tìm hiểu các tesuji băm-trục:

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

nó sẽ là tuyệt vời nếu bạn thêm một số bình luận để hiểu những gì đang xảy ra ở đây –

-1

Có lẽ đây sẽ giúp bạn. Nó nằm trong 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

bảng Pivot như có thể dễ dàng tính toán với thư viện NReco.PivotData hợp miễn phí:

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 và cột phím được đại diện bởi pvtTbl.RowKeys và pvtTbl.ColumnKeys bộ sưu tập; các giá trị/tổng số có thể được truy cập bởi bộ chỉ mục (ví dụ: pvtTbl[0,0].Value) hoặc theo hàng + cột khóa (ví dụ: pivotData[new Key(new DateTime(2012, 3, 30, 11, 42, 00)), new Key(4)].Value).

+1

Tôi khá chắc chắn ông đã yêu cầu làm thế nào để làm điều đó bản thân và không sử dụng một thư viện. Thư viện rất tốt nhưng không phải là câu trả lời. – Jon

0

Một đoạn mã nhỏ xoay quanh bất kỳ bảng bạn muốn:

 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()); 
     } 
Các vấn đề liên quan