0

我正在尝试使用以下代码来创建 PIVOT,但它不起作用。

它给了我编译时错误。我不知道 linq 所以无法使用它。

请帮忙 :

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

代码来自: http: //michaeljswart.com/2011/06/forget-about-pivot/

此外,它尝试使用以下代码,它运行良好,除了它没有给出值列的总和

public DataTable GetInversedDataTable(DataTable table, string columnX, string columnY, string columnZ, string nullValue, bool sumValues)
        {
            //Create a DataTable to Return
            DataTable returnTable = new DataTable();

            DataTable tempTable = table.Clone();

            if (string.IsNullOrEmpty(columnX))
            {
                columnX = table.Columns[0].ColumnName;
            }

            tempTable.Columns.Remove(columnX);


            //Add a Column at the beginning of the table
            //returnTable.Columns.Add(columnY);

            returnTable = tempTable.Clone();

            //Read all DISTINCT values from columnX Column in the provided DataTale
            List<string> columnXValues = new List<string>();


            foreach (DataRow dr in table.Rows)
            {
                string columnXTemp = dr[columnX].ToString();
                if (!columnXValues.Contains(columnXTemp))
                {
                    //Read each row value, if it's different from others provided, add to the list of values and creates a new Column with its value.
                    columnXValues.Add(columnXTemp);
                    returnTable.Columns.Add(columnXTemp);
                }
            }

            //Verify if Y and Z Axis columns re provided
            if (!string.IsNullOrEmpty(columnY) && !string.IsNullOrEmpty(columnZ))
            {
                //Read DISTINCT Values for Y Axis Column
                List<string> columnYValues = new List<string>();

                foreach (DataRow dr in table.Rows)
                {
                    if (!columnYValues.Contains(dr[columnY].ToString()))
                    {
                        columnYValues.Add(dr[columnY].ToString());
                    }
                }

                //Loop all Column Y Distinct Value
                foreach (string columnYValue in columnYValues)
                {
                    //Creates a new Row
                    DataRow drReturn = returnTable.NewRow();
                    drReturn[0] = columnYValue;
                    //foreach column Y value, The rows are selected distincted
                    DataRow[] rows = table.Select((columnY + "='") + columnYValue + "'");

                    //Read each row to fill the DataTable
                    foreach (DataRow dr in rows)
                    {
                        string rowColumnTitle = dr[columnX].ToString();

                        //Read each column to fill the DataTable
                        foreach (DataColumn dc in returnTable.Columns)
                        {
                            if (dc.ColumnName == rowColumnTitle)
                            {
                                //If Sum of Values is True it try to perform a Sum
                                //If sum is not possible due to value types, the value displayed is the last one read
                                if (sumValues)
                                {
                                    try
                                    {
                                        drReturn[rowColumnTitle] = Convert.ToDecimal(drReturn[rowColumnTitle]) + Convert.ToDecimal(dr[columnZ]);
                                    }
                                    catch
                                    {
                                        drReturn[rowColumnTitle] = dr[columnZ];
                                    }
                                }
                                else
                                {
                                    drReturn[rowColumnTitle] = dr[columnZ];

                                }
                            }
                        }
                    }

                    returnTable.Rows.Add(drReturn);

                }
            }
            else
            {
                throw new Exception("The columns to perform inversion are not provided");
            }

            //if a nullValue is provided, fill the datable with it
            if (!string.IsNullOrEmpty(nullValue))
            {
                foreach (DataRow dr in returnTable.Rows)
                {
                    foreach (DataColumn dc in returnTable.Columns)
                    {
                        if (string.IsNullOrEmpty(dr[dc.ColumnName].ToString()))
                        {
                            dr[dc.ColumnName] = nullValue;
                        }
                    }
                }
            }

            return returnTable;
        }

GetInversedDataTable(dtNormal, "Dated", "OrderStatus", "Qty", " ", true);

请帮忙 :)

4

2 回答 2

5

以下是更正编译错误的代码:

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

我改为Cast(<DataColumn>)Cast<DataColumn>()两个位置,并去掉了 lambda 表达式中间的分号。你问题的第二部分有点棘手。你可能想把它当作自己的问题来问。

于 2012-10-13T03:37:51.730 回答
1

好一个。,但你可能想替换下面的行

 .ForEach (c => result.Columns.Add(c, pivotColumn.DataType));

有了这个(将pivotColumn更改为pivotValue)

 .ForEach (c => result.Columns.Add(c, pivotValue.DataType));

非常适合我的要求。

于 2014-01-15T09:13:36.470 回答