附件: PivotTable.gif

Introduction


Pivot transformation is very useful to summarize Data in a flat data table (Columns and Rows), providing a more clean visualization of the data.

In this article it will be shown 2 methods to retrieve Pivot and Inverted tables from a DataTable.

This methods are very useful, specially for those using Metadata to retrieve information from database, or those that can not use PIVOT Transformation from SQL SERVER 2005

http://msdn2.microsoft.com/en-us/library/ms140308.aspx

The two methods are independent but complement each other in a way that data can be manipulated to return the table inversted or a more complex pivot table.

The Pivot Methods

1st - Simple Inversion

Read all Data and return all Columns as Lines and Lines as Columns.

The X Axis Column provided is used as Column Header and some Column may be ignored in the process if desired so.
  1.         /// <summary>
  2.         /// Gets a Inverted DataTable
  3.         /// </summary>
  4.         /// <param name="table">DataTable do invert</param>
  5.         /// <param name="columnX">X Axis Column</param>
  6.         /// <param name="nullValue">null Value to Complete the Pivot Table</param>
  7.         /// <param name="columnsToIgnore">Columns that should be ignored in the pivot
  8.         /// process (X Axis column is ignored by default)</param>
  9.         /// <returns>C# Pivot Table Method  - Felipe Sabino</returns>
  10.         public static DataTable GetInversedDataTable(DataTable table, string columnX,
  11.                                                     params string[] columnsToIgnore)
  12.         {
  13.             //Create a DataTable to Return
  14.             DataTable returnTable = new DataTable();

  15.             if (columnX == "")
  16.                 columnX = table.Columns[0].ColumnName;

  17.             //Add a Column at the beginning of the table

  18.             returnTable.Columns.Add(columnX);

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

  21.             //Creates list of columns to ignore
  22.             List<string> listColumnsToIgnore = new List<string>();
  23.             if (columnsToIgnore.Length > 0)
  24.                 listColumnsToIgnore.AddRange(columnsToIgnore);

  25.             if (!listColumnsToIgnore.Contains(columnX))
  26.                 listColumnsToIgnore.Add(columnX);

  27.             foreach (DataRow dr in table.Rows)
  28.             {
  29.                 string columnXTemp = dr[columnX].ToString();
  30.                 //Verify if the value was already listed
  31.                 if (!columnXValues.Contains(columnXTemp))
  32.                 {
  33.                     //if the value id different from others provided, add to the list of
  34.                     //values and creates a new Column with its value.
  35.                     columnXValues.Add(columnXTemp);
  36.                     returnTable.Columns.Add(columnXTemp);
  37.                 }
  38.                 else
  39.                 {
  40.                     //Throw exception for a repeated value
  41.                     throw new Exception("The inversion used must have unique values for column " + columnX);
  42.                 }
  43.             }

  44.             //Add a line for each column of the DataTable

  45.             foreach (DataColumn dc in table.Columns)
  46.             {
  47.                 if (!columnXValues.Contains(dc.ColumnName) && !listColumnsToIgnore.Contains(dc.ColumnName))
  48.                 {
  49.                     DataRow dr = returnTable.NewRow();
  50.                     dr[0] = dc.ColumnName;
  51.                     returnTable.Rows.Add(dr);
  52.                 }
  53.             }

  54.             //Complete the datatable with the values
  55.             for (int i = 0; i < returnTable.Rows.Count; i++)
  56.             {
  57.                 for (int j = 1; j < returnTable.Columns.Count; j++)
  58.                 {
  59.                     returnTable.Rows[j] = table.Rows[j - 1][returnTable.Rows[0].ToString()].ToString();
  60.                 }
  61.             }

  62.             return returnTable;
  63.         }
复制代码
2nd - Pivoting

It used the Idea of 3 Axis to build the new table.

The X Axis Column is the column with the Unique Values to build the Columns Header

The Y Axis Values is the column with the values to be displayed as the Rows in the First Column.

The Z Axis is the "value". Is the match of X and Y in the DataSource and can be the sum of values if more than one different value is found n the process.

The Null Value is provided in case there is the need to fill the empty Cells of the Table with a Certain Value.

The flag to sum values is used in case there is more than one value for a certain X and Y Column combination, if it is provided as "false" the last value that is read is displayed.
  1.       /// <summary>
  2.         /// Gets a Inverted DataTable
  3.         /// </summary>
  4.         /// <param name="table">Provided DataTable</param>
  5.         /// <param name="columnX">X Axis Column</param>
  6.         /// <param name="columnY">Y Axis Column</param>
  7.         /// <param name="columnZ">Z Axis Column (values)</param>
  8.         /// <param name="columnsToIgnore">Whether to ignore some column, it must be
  9.         /// provided here</param>
  10.         /// <param name="nullValue">null Values to be filled</param>
  11.         /// <returns>C# Pivot Table Method  - Felipe Sabino</returns>
  12.         public static DataTable GetInversedDataTable(DataTable table, string columnX,
  13.             string columnY, string columnZ, string nullValue, bool sumValues)
  14.         {
  15.             //Create a DataTable to Return
  16.             DataTable returnTable = new DataTable();

  17.             if (columnX == "")
  18.                 columnX = table.Columns[0].ColumnName;

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


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

  23.             foreach (DataRow dr in table.Rows)
  24.             {

  25.                 string columnXTemp = dr[columnX].ToString();
  26.                 if (!columnXValues.Contains(columnXTemp))
  27.                 {
  28.                     //Read each row value, if it's different from others provided, add to
  29.                     //the list of values and creates a new Column with its value.
  30.                     columnXValues.Add(columnXTemp);
  31.                     returnTable.Columns.Add(columnXTemp);
  32.                 }
  33.             }

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

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

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

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

  56.                         //Read each column to fill the DataTable
  57.                         foreach (DataColumn dc in returnTable.Columns)
  58.                         {
  59.                             if (dc.ColumnName == rowColumnTitle)
  60.                             {
  61.                                 //If Sum of Values is True it try to perform a Sum
  62.                                 //If sum is not possible due to value types, the value
  63.                                 // displayed is the last one read
  64.                                 if (sumValues)
  65.                                 {
  66.                                     try
  67.                                     {
  68.                                         drReturn[rowColumnTitle] =
  69.                                             Convert.ToDecimal(drReturn[rowColumnTitle]) +
  70.                                             Convert.ToDecimal(dr[columnZ]);
  71.                                     }
  72.                                     catch
  73.                                     {
  74.                                         drReturn[rowColumnTitle] = dr[columnZ];
  75.                                     }
  76.                                 }
  77.                                 else
  78.                                 {
  79.                                     drReturn[rowColumnTitle] = dr[columnZ];
  80.                                 }
  81.                                
  82.                             }
  83.                         }
  84.                     }

  85.                     returnTable.Rows.Add(drReturn);
  86.                 }

  87.             }
  88.             else
  89.             {
  90.                 throw new Exception("The columns to perform inversion are not provided");
  91.             }

  92.             //if a nullValue is provided, fill the datable with it
  93.             if (nullValue != "")
  94.             {
  95.                 foreach (DataRow dr in returnTable.Rows)
  96.                 {
  97.                     foreach (DataColumn dc in returnTable.Columns)
  98.                     {
  99.                         if (dr[dc.ColumnName].ToString() == "")
  100.                             dr[dc.ColumnName] = nullValue;
  101.                     }
  102.                 }
  103.             }

  104.             return returnTable;
  105.         }
复制代码
TOP