Tuesday, September 28, 2010

ASP.NET Gridview - Group Header Rows and Export to Excel

I'm working on an ASP.NET portal project that has 2 very common blocks of code in it, but could not find good information on integrating these two together.

First I need to great a group header row on my gridview to collect related columns together. A typical example is to create a gridview with headers like this:

Group 1Group 2
CountAmountCountAmount

This can be accomplished in the GridView's DataBound event and adding the extra row above the header. A typical code example can be found here.  So far so good.

Of course, our users also want to be able to export the results of these grids to Excel. Again, a very common task. An example of implementing this code can be found here.

The only problem comes when you try to use both. The grid looks great on your webpage, but when you export it to Excel, you only get the original row from the designer - not the new group header row.  The other day I decided to get to the bottom of this.

The export class pulls the header information from the gridview through the HeaderRow property. As the name implies, it only returns a single row. So I went exploring through the various properties of the gridview to see what else I could find.

The code that adds the group header is based on the premise that gridview.Controls[0] can be cast as a Table to get the table representation of the entire grid. A table of course contains a collection of Rows. Now each row has a property on it called TableSection, which is an enumerated type with values TableHeader, TableBody, and TableFooter. However, I found something interesting: the rows created by the default gridview all have the TableSection property set to TableBody - even the header row.

I decided to exploit this in my code. In the DataBound event, before adding my new row to the header, I simply set the TableSection property to TableHeader:

if (t != null)
{
row.TableSection = TableRowSection.TableHeader;
t.Rows.AddAt(0, row);
}

This allows my new header row to be differentiated from the default header. I use this to identify the row in my export to excel class:

if (gv.HeaderRow != null)
{
// Check for extra header rows created
Table GridAsTable = (Table)gv.Controls[0];
if (GridAsTable.Rows[0].TableSection == TableRowSection.TableHeader)
{
GridViewExportUtil.PrepareControlForExport(GridAsTable.Rows[0]);
table.Rows.Add(GridAsTable.Rows[0]);
}

// Now add the "normal" header row
GridViewExportUtil.PrepareControlForExport(gv.HeaderRow);
table.Rows.Add(gv.HeaderRow);
}

Of course, this code only allows one additional header row to be exported - if you have need for more simply loop through the Rows and find all those flagged with TableHeader.

In the end I found this was a very simple solution to the problem, and my users can now see the column group titles when exporting to Excel.

3 comments:

  1. This is great, searched everywhere for this! But maybe you have these lines in VB to for datagrid? Couldn't really find something similare that works..

    ReplyDelete
  2. Can you explain the same in detail.or put the entire code.

    ReplyDelete