Click here to Skip to main content
15,884,030 members
Articles / Web Development / ASP.NET

Pivoting DataTable Simplified

Rate me:
Please Sign up or sign in to vote.
4.92/5 (131 votes)
20 Aug 2014CPOL5 min read 426.5K   28.6K   325  
A class to pivot a DataTable with various aggregate functions
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Data;

// Written by Anurag Gandhi.
// Url: http://www.gandhisoft.com
// Contact me at: soft.gandhi@gmail.com
public partial class _Default : System.Web.UI.Page 
{
    string _Separator = ".";

    protected void Page_Load(object sender, EventArgs e)
    {
        if (!IsPostBack)
        {
            BindGridView();
        }
    }

    //Binds all the GridView used in the page.//
    private void BindGridView()
    {
        // Retrieve the data table from Excel Data Source.
        DataTable dt = ExcelLayer.GetDataTable("_Data\\DataForPivot.xls", "Sheet1$");  
        Pivot pvt = new Pivot(dt);

        grdRawData.DataSource = dt;
        grdRawData.DataBind();

        grdCompanyYear.DataSource = pvt.PivotData("Company", "CTC", AggregateFunction.Count, "Year");
        grdCompanyYear.DataBind();
        grdLeastCompanyYear.DataSource = pvt.PivotData("Company", "CTC", AggregateFunction.Min, "Year");
        grdLeastCompanyYear.DataBind();

        grdDesignationCompanyYear.DataSource = pvt.PivotData("Designation", "CTC", AggregateFunction.Max, "Company", "Year");
        grdDesignationCompanyYear.DataBind();
        grdDesignationCompanyYearAvg.DataSource = pvt.PivotData("Designation", "CTC", AggregateFunction.Average, "Company", "Year");
        grdDesignationCompanyYearAvg.DataBind();

        grdPivot.DataSource = pvt.PivotData("Designation", "CTC", AggregateFunction.Max, "Company", "Department", "Year");
        grdPivot.DataBind();
    }
    protected void grdPivot2_RowCreated(object sender, GridViewRowEventArgs e)
    {
        if (e.Row.RowType == DataControlRowType.Header)
            MergeHeader((GridView)sender, e.Row, 2);
    }
    protected void grdPivot3_RowCreated(object sender, GridViewRowEventArgs e)
    {
        if (e.Row.RowType == DataControlRowType.Header)
            MergeHeader((GridView)sender, e.Row, 3);
    }

    /// <summary>
    /// Function used to Create and Merge the Header Cells based on the Pivot conditions.
    /// </summary>
    /// <param name="gv">GridView</param>
    /// <param name="row">Header Row of the GridView</param>
    /// <param name="PivotLevel">The no. of ColumnFields used to Pivot the data</param>
    private void MergeHeader(GridView gv, GridViewRow row, int PivotLevel)
    {
        for (int iCount = 1; iCount <= PivotLevel; iCount++)
        {
            GridViewRow oGridViewRow = new GridViewRow(0, 0, DataControlRowType.Header, DataControlRowState.Insert);
            var Header = (row.Cells.Cast<TableCell>()
                .Select(x => GetHeaderText(x.Text, iCount, PivotLevel)))
                .GroupBy(x => x);

            foreach (var v in Header)
            {
                TableHeaderCell cell = new TableHeaderCell();
                cell.Text = v.Key.Substring(v.Key.LastIndexOf(_Separator) + 1);
                cell.ColumnSpan = v.Count();
                oGridViewRow.Cells.Add(cell);
            }
            gv.Controls[0].Controls.AddAt(row.RowIndex, oGridViewRow);
        }
        row.Visible = false;
    }
    private string GetHeaderText(string s, int i, int PivotLevel)
    {
        if (!s.Contains(_Separator) && i != PivotLevel)
            return string.Empty;
        else
        {
            int Index = NthIndexOf(s, _Separator, i);
            if (Index == -1)
                return s;
            return s.Substring(0, Index);
        }
    }

    /// <summary>
    /// Returns the nth occurance of the SubString from string str
    /// </summary>
    /// <param name="str">source string</param>
    /// <param name="SubString">SubString whose nth occurance to be found</param>
    /// <param name="n">n</param>
    /// <returns>Index of nth occurance of SubString if found else -1</returns>
    private int NthIndexOf(string str, string SubString, int n)
    {
        int x = -1;
        for (int i = 0; i < n; i++)
        {
            x = str.IndexOf(SubString, x + 1);
            if (x == -1)
                return x;
        }
        return x;
    }
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Architect
India India
Anurag Gandhi is a Freelance Developer and Consultant, Architect, Blogger, Speaker, and Ex Microsoft Employee. He is passionate about programming.
He is extensively involved in Asp.Net Core, MVC/Web API, Node/Express, Microsoft Azure/Cloud, web application hosting/architecture, Angular, AngularJs, design, and development. His languages of choice are C#, Node/Express, JavaScript, Asp .NET MVC, Asp, C, C++. He is familiar with many other programming languages as well. He mostly works with MS SQL Server as the preferred database and has worked with Redis, MySQL, Oracle, MS Access, etc. also.
He is active in programming communities and loves to share the knowledge with others whenever he gets the time for it.
He is also a passionate chess player.
Linked in Profile: https://in.linkedin.com/in/anuraggandhi
He can be contacted at soft.gandhi@gmail.com

Comments and Discussions