0

我有以下将普通数据表转换为数据透视表的函数。

但我还有 1 个要求,它还应该显示 Value 列,即所有 Pivot 列单元格的总和。

e.g. : ORDER | SUM | PLANDATE
         1      50    10-Oct-2012
         1      10    10-Oct-2012
         2      15    12-Oct-2012

PIVOT 之后应该是这样的

ORDER | SUM | 10-Oct-2012 | 12-Oct-2012
  1      60     50            10
  2      15                   15

我的枢轴功能是:

DataTable Pivot(DataTable dt, DataColumn pivotColumn, DataColumn pivotValue) {
    // find primary key columns 
    //(i.e. everything but pivot column and pivot value)
    DataTable temp = dt.Copy();
    temp.Columns.Remove( pivotColumn.ColumnName );
    temp.Columns.Remove( pivotValue.ColumnName );
    string[] pkColumnNames = temp.Columns.Cast<DataColumn>()
        .Select( c => c.ColumnName )
        .ToArray();

    // prep results table
    DataTable result = temp.DefaultView.ToTable(true, pkColumnNames).Copy();
    result.PrimaryKey = result.Columns.Cast<DataColumn>().ToArray();
    dt.AsEnumerable()
        .Select(r => r[pivotColumn.ColumnName].ToString())
        .Distinct().ToList()
        .ForEach (c => result.Columns.Add(c, pivotColumn.DataType));

    // load it
    foreach( DataRow row in dt.Rows ) {
        // find row to update
        DataRow aggRow = result.Rows.Find(
            pkColumnNames
                .Select( c => row[c] )
                .ToArray() );
        // the aggregate used here is LATEST 
        // adjust the next line if you want (SUM, MAX, etc...)
        aggRow[row[pivotColumn.ColumnName].ToString()] = row[pivotValue.ColumnName];
    }

    return result;
}

谢谢&任何帮助都会得到帮助...

Sample Data :
 OrderStatus    Qty     Dated
    New 100 10-Oct-2012
    New 150 10-Oct-2012
    New 100 10-Oct-2012
    Conf    200 12-Oct-2012
    New 100 12-Oct-2012
    Reconf  300 12-Oct-2012
    New 200 15-Oct-2012
    New 200 15-Oct-2012
    Reconf  100 18-Oct-2012
    New 150 18-Oct-2012
    Conf    150 18-Oct-2012
    New 100 20-Oct-2012
    Reconf  500 20-Oct-2012
    New 100 30-Oct-2012
    New 700 30-Oct-2012
    New 100 30-Oct-2012
    Conf    100 10-Oct-2012

更新代码

 private DataTable DataTableToPivot(DataTable dtNormalTable, DataColumn pivotColumn, DataColumn valueColumn)
            {
                cTracing.WriteTrace("Inside DataTableToPivot", "DataTableToPivot");

                DataTable dtPivot = null;
                DataTable tempPivot = null;
                DataColumn sumColumn = new DataColumn();
                string[] pkColumnNames = null;

                try
                {
                    sumColumn.ColumnName = valueColumn.ColumnName;
                    sumColumn.DataType = typeof(string);
                    sumColumn.DefaultValue = "0";

var allrows = dt.AsEnumerable().Select(delegate(DataRow r)
            {
                DataRow nr = dt.NewRow();
                foreach (DataColumn item in dt.Columns)
                {
                    nr.SetField(item.ColumnName, r[item.ColumnName] is DBNull ? string.Empty : r[item.ColumnName]);
                }
                return nr;
            });

            dtNormalTable = allrows.CopyToDataTable();

                    // find primary key columns 
                    //(i.e. everything but pivot column and pivot value)
                    tempPivot = dtNormalTable.Copy();

                    tempPivot.Columns.Remove(pivotColumn.ColumnName);
                    tempPivot.Columns.Remove(valueColumn.ColumnName);

                    pkColumnNames = tempPivot.Columns
                                                 .Cast<DataColumn>()
                                                 .Select(c => c.ColumnName)
                                                 .ToArray();

                    // prep results table
                    dtPivot = tempPivot.DefaultView.ToTable(true, pkColumnNames).Copy();
                    dtPivot.PrimaryKey = dtPivot.Columns.Cast<DataColumn>().ToArray();
                    // include the sum column
                    dtPivot.Columns.Add(sumColumn);
                    try
                    {
                        dtNormalTable.AsEnumerable()
                          .Select(r => r[pivotColumn.ColumnName].ToString())
                          .Distinct()
                          .ToList()
                          .ForEach(c => dtPivot.Columns.Add(Convert.ToDateTime(c).ToString("dd-MMM-yyyy"), typeof(string)));
                    }
                    catch
                    {
                        dtNormalTable.AsEnumerable()
                          .Select(r => r[pivotColumn.ColumnName].ToString())
                          .Distinct()
                          .ToList()
                          .ForEach(c => dtPivot.Columns.Add(c, typeof(string)));
                    }

                    // load it
                    foreach (DataRow row in dtNormalTable.Rows)
                    {
                        // find row to update
                        DataRow aggRow = dtPivot.Rows.Find(
                            pkColumnNames
                                         .Select(c => row[c])
                                         .ToArray());
                        // the aggregate used here is LATEST 
                        // adjust the next line if you want (SUM, MAX, etc...)
                        string columnName = string.Empty;
                        try
                        {
                            columnName = Convert.ToDateTime(row[pivotColumn.ColumnName]).ToString("dd-MMM-yyyy");
                        }
                        catch
                        {
                            columnName = row[pivotColumn.ColumnName].ToString();
                        }

                        if (aggRow.IsNull(columnName))
                        {
                            aggRow[columnName] = Convert.ToDecimal(row[valueColumn.ColumnName]);
                        }
                        else
                        {
                            aggRow[columnName] = Convert.ToDecimal(aggRow[columnName]) +
                                                 Convert.ToDecimal(row[valueColumn.ColumnName]);
                        }

                        if (numberFormat == "3")
                        {
                            // add the value to the sum
                            aggRow[sumColumn] = (Convert.ToDecimal(aggRow[sumColumn].ToString()) +
                                                Convert.ToDecimal(row[valueColumn.ColumnName].ToString())).ToString("#0.000");
                        }
                        else if (numberFormat == "2")
                        {
                            // add the value to the sum
                            aggRow[sumColumn] = (Convert.ToDecimal(aggRow[sumColumn].ToString()) +
                                                Convert.ToDecimal(row[valueColumn.ColumnName].ToString())).ToString("#0.00");
                        }
                        else if (numberFormat == "1")
                        {
                            // add the value to the sum
                            aggRow[sumColumn] = (Convert.ToDecimal(aggRow[sumColumn].ToString()) +
                                                Convert.ToDecimal(row[valueColumn.ColumnName].ToString())).ToString("#0.0");
                        }
                        else
                        {
                            // add the value to the sum
                            aggRow[sumColumn] = (Convert.ToDecimal(aggRow[sumColumn].ToString()) +
                                                Convert.ToDecimal(row[valueColumn.ColumnName].ToString())).ToString("#0");
                        }
                    }

                    return dtPivot;
                }
                catch (Exception ex)
                {
                    cTracing.WriteTrace("Error inside DataTableToPivot", "DataTableToPivot");
                    cLogging.WriteLog(ex);
                    return null;
                }
                finally
                {
                    if (dtPivot != null)
                        dtPivot.Dispose();
                }
            }
enter code here
4

1 回答 1

1

如何将每一行的值添加到相应聚合行中的总和列?

DataTable Pivot(DataTable dt, DataColumn pivotColumn, DataColumn pivotValue) {
    DataColumn sumColumn = new DataColumn();
    sumColumn.ColumnName = "SUM";
    sumColumn.DataType = typeof(int);
    sumColumn.DefaultValue = 0;

    // find primary key columns 
    //(i.e. everything but pivot column and pivot value)
    DataTable temp = dt.Copy();
    temp.Columns.Remove( pivotColumn.ColumnName );
    temp.Columns.Remove( pivotValue.ColumnName );
    string[] pkColumnNames = temp.Columns.Cast<DataColumn>()
        .Select( c => c.ColumnName )
        .ToArray();

    // prep results table
    DataTable result = temp.DefaultView.ToTable(true, pkColumnNames).Copy();
    result.PrimaryKey = result.Columns.Cast<DataColumn>().ToArray();
    // include the sum column
    result.Columns.Add(sumColumn);
    dt.AsEnumerable()
        .Select(r => r[pivotColumn.ColumnName].ToString())
        .Distinct()
        .OrderBy(c => Convert.ToDateTime(c))   // Order by the date
        .ToList()
        .ForEach (c => result.Columns.Add(c, pivotColumn.DataType));

    // load it
    foreach( DataRow row in dt.Rows ) {
        // find row to update
        DataRow aggRow = result.Rows.Find(
            pkColumnNames
                .Select( c => row[c] )
                .ToArray() );
        // the aggregate used here is LATEST 
        // adjust the next line if you want (SUM, MAX, etc...)
        string columnName = row[pivotColumn.ColumnName].ToString();
        if(aggRow.IsNull(columnName))
        {
            aggRow[columnName] = (int)row[pivotValue.ColumnName];          
        }
        else
        {
            aggRow[columnName] = Convert.ToInt32(aggRow[columnName]) +
                                 (int)row[pivotValue.ColumnName];
        }   
        // add the value to the sum
        aggRow[sumColumn] = (int)aggRow[sumColumn] + 
                            (int)row[pivotValue.ColumnName];
    }

    return result;
}
于 2012-10-21T17:41:50.300 回答