Создание сводной таблицы из DataTable

Я использую winforms С# для создания приложения, которое должно превратить datatable в сводную таблицу. У меня сводная таблица работает отлично с конца SQL, но создание ее из datatable кажется более сложным. Похоже, я не мог найти что-либо, встроенное в .NET для этого.

. Примечание: Я должен сделать это со стороны,.NET, как я манипулировать данными до создания шарнира

Я прочитал некоторые статьи, которые делали некоторые подобные вещи, но это было трудно применить к моей проблеме.

* У меня есть datatable с столбцами "StartDateTime", "Tap" и "Data". Стартовые таблицы должны быть сгруппированы вместе, а значения данных усреднены (иногда более одного значения данных за начальную дату). Таблица показана ниже:

enter image description here

Сводная таблица должна выводиться, как показано ниже (не округленные значения). Номера столбцов - это разные номера каналов (по одному для каждого уникального).

Pivot Table

Как я могу создать эту сводную таблицу из datatable?

EDIT: забыли упомянуть, эти значения отвода не всегда от 1 до 4, они различаются по количеству и значению.

Ответ 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

Ответ 2

Таблицу сводных таблиц можно легко вычислить со свободной 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).

Ответ 3

Еще одна небольшая часть кода для поворота любой таблицы, которую вы хотите:

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

Ответ 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