How to create pivot table in C# and display it in DataGrid?
NOTE: it is available
version 2.0 of PivotTable
It exists
well-know solution for pre-sorted and pre-grouped values.
What if we would like to pivot free set? Sample below will pivot any DataTable and produce new summarized DataTable. You can pivot Array or ArrayList also, first you should convert your Array to DataTable and then call Pivot method. Data is ready to display in grid.
public DataTable Pivot(
DataTable src,
string VerticalColumnName,
string HorizontalColumnName,
string ValueColumnName )
{
DataTable dst = new DataTable();
if (src == null || src.Rows.Count == 0)
return dst;
// find all distinct names for column and row
ArrayList ColumnValues = new ArrayList();
ArrayList RowValues = new ArrayList();
foreach (DataRow dr in src.Rows)
{
// find all column values
object column = dr[VerticalColumnName];
if (!ColumnValues.Contains(column))
ColumnValues.Add(column);
//find all row values
object row = dr[HorizontalColumnName];
if (!RowValues.Contains(row))
RowValues.Add(row);
}
ColumnValues.Sort();
RowValues.Sort();
//create columns
dst = new DataTable();
dst.Columns.Add(VerticalColumnName, src.Columns[VerticalColumnName].DataType);
Type t = src.Columns[ValueColumnName].DataType;
foreach (object ColumnNameInRow in RowValues) {
dst.Columns.Add(ColumnNameInRow.ToString(), t);
}
//create destination rows
foreach (object RowName in ColumnValues) {
DataRow NewRow = dst.NewRow();
NewRow[VerticalColumnName] = RowName.ToString();
dst.Rows.Add(NewRow);
}
//fill out pivot table
foreach (DataRow drSource in src.Rows) {
object key = drSource[VerticalColumnName];
string ColumnNameInRow = Convert.ToString(drSource[HorizontalColumnName]);
int index = ColumnValues.IndexOf(key);
dst.Rows[index][ColumnNameInRow] = sum(dst.Rows[index][ColumnNameInRow], drSource[ValueColumnName]);
}
return dst;
}
dynamic sum(dynamic a, dynamic b) {
if (a is DBNull && b is DBNull)
return DBNull.Value;
else if (a is DBNull && !(b is DBNull))
return b;
else if (!(a is DBNull) && b is DBNull)
return a;
else
return a + b;
}
Proof:
object DBNULL = DBNull.Value;
DataTable src = new DataTable();
DataTable dst = null;
src.Columns.Add("City", typeof(string));
src.Columns.Add("Product", typeof(string));
src.Columns.Add("Value", typeof(float));
src.Rows.Add("City A", "Product 1", 1.2f);
src.Rows.Add("City C", "Product 2", 0.3f);
src.Rows.Add("City A", "Product 1", 1.0f);
src.Rows.Add("City B", "Product 3", 2.2f);
src.Rows.Add("City B", "Product 1", 1.5f);
src.Rows.Add("City A", "Product 2", 0.8f);
src.Rows.Add("City A", "Product 4", 1.1f);
PivotTable test = new PivotTable();
dst = test.Pivot(src, "City", "Product", "Value");
CollectionAssert.AreEqual(new object[] { "City A", 2.2f, 0.8f, DBNULL, 1.1f }, dst.Rows[0].ItemArray);
CollectionAssert.AreEqual(new object[] { "City B", 1.5f, DBNULL, 2.2f, DBNULL }, dst.Rows[1].ItemArray);
CollectionAssert.AreEqual(new object[] { "City C", DBNULL, 0.3f, DBNULL, DBNULL }, dst.Rows[2].ItemArray);
Enjoy!