winforms 从数据表创建数据透视表

4dbbbstv  于 2023-05-29  发布在  其他
关注(0)|答案(5)|浏览(213)

我正在使用C# winforms创建一个需要将数据表转换为透视表的应用程序。我让数据透视表在SQL端工作得很好,但从数据表创建它似乎更棘手。我似乎找不到任何内置于.NET的东西。
注意:我必须从.NET端执行此操作,因为我在创建透视表之前操作数据。
我读过一些类似的文章,但我很难将它们应用到我的问题中。

  • 我有一个数据表,列为“StartDateTime”,“Tap”和“Data”。应将开始日期分组在一起,并对数据值取平均值(有时每个开始日期有多个数据值)。表格如下所示:

数据透视表的输出应该像下面的图像(虽然不是四舍五入的值)。列编号是不同的抽头编号(每个抽头编号对应一个唯一的抽头编号)。

如何从数据表创建这个透视表?
编辑:忘了说了,这些抽头值并不总是从1-4,它们确实在数量和值上有所不同。

pes8fvy9

pes8fvy91#

学习hash-pivot tesuji:

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
ix0qys7i

ix0qys7i2#

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

rmbxnbpk

rmbxnbpk3#

也许这个能帮到你在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
zlhcx6iw

zlhcx6iw4#

另一小段代码可以透视任何你想要的表:

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

bqf10yzr5#

你可以试试下面的函数(C#代码):
用途:
请注意,您可以在第二个参数中添加所需的列数。

DataTable pivot = PivotTable(t, "Tap", "Data");

功能:

public DataTable PivotTable(DataTable table, string pivotColumn, params string[] includeColumns)
{
    if (table.Columns.IndexOf(pivotColumn) == -1)
        throw new Exception(string.Format("PivotColumn {0} could not be found.", pivotColumn));

    // Clone the table
    DataTable t = table.Clone();
    foreach (DataRow r in table.Rows)
        t.Rows.Add(r.ItemArray);

    DataTable distinctValues = t.DefaultView.ToTable(true, pivotColumn);
    int maxRowIndex = 0;
    for (int i = 0; i < distinctValues.Rows.Count; i++)
    {
        // Add Pivot Column
        string pivotedName = string.Concat(pivotColumn, (i + 1));
        t.Columns.Add(new DataColumn(pivotedName, t.Columns[pivotColumn].DataType));

        // Add rows as columns 
        DataRow row = distinctValues.Rows[i];
        string value = row[pivotColumn].ToString();

        if(includeColumns != null)
        {
            for (int j = 0; j < includeColumns.Length; j++) 
            {
                if (t.Columns.IndexOf(includeColumns[j]) == -1)
                    continue;
                t.Columns.Add(new DataColumn(string.Concat(value, includeColumns[j]), t.Columns[includeColumns[j]].DataType));
            }                        
        }

        // Fill new columns
        DataRow[] select = t.Select(string.Format("{0}='{1}'", pivotColumn, value));
        maxRowIndex = Math.Max(maxRowIndex, select.Length);
        for (int j = 0; j < select.Length; j++)
        {
            DataRow r = select[j];
            t.Rows[j][pivotedName] = r[pivotColumn];
            if (includeColumns != null)
            {
                for (int k = 0; k < includeColumns.Length; k++)
                {
                    if (t.Columns.IndexOf(includeColumns[k]) == -1)
                        continue;

                    string colName = string.Concat(value, includeColumns[k]);
                    t.Rows[j][colName] = r[includeColumns[k]];
                }
            }
        }
    }

    // Remove original columns
    t.Columns.Remove(pivotColumn);
    foreach (string c in includeColumns)
        t.Columns.Remove(c);

    // Remove pivoted rows
    if(maxRowIndex > 0)
    {
        while (maxRowIndex < t.Rows.Count)
            t.Rows.RemoveAt(maxRowIndex);
    }
    return t;
}

相关问题