You are on page 1of 4

Export GridView to Excel within an

UpdatePanel
There’s a ton of information online about exporting a DataGrid or GridView to Excel, but
most variations do not consider the GridView may reside within an UpdatePanel. It goes
without saying, but I was disappointed when I recently dusted off my “Export GridView
to Excel” code snippet and encountered a number of exceptions. So I revisited a number
of links and I collected a working solution. If you need a “simple” way to export your
GridView to Excel and you are using an UpdatePanel, I hope the following code finds
you well:

protected void btnExport_Click(object sender, EventArgs e)


{
// Reference your own GridView here
if (AccountGrid.Rows.Count > 65535)
{
DisplayError("Export to Excel is not allowed" +
"due to excessive number of rows.");
return;
}

string filename = String.Format("Results_{0}_{1}.xls",


DateTime.Today.Month.ToString(),
DateTime.Today.Year.ToString());

Response.Clear();
Response.AddHeader("Content-Disposition", "attachment;filename=" +
filename);
Response.Charset = "";

// SetCacheability doesn't seem to make a difference (see update)


Response.Cache.SetCacheability(System.Web.HttpCacheability.NoCache)
;

Response.ContentType = "application/vnd.xls";

System.IO.StringWriter stringWriter = new System.IO.StringWriter();


System.Web.UI.HtmlTextWriter htmlWriter = new
HtmlTextWriter(stringWriter);

// Replace all gridview controls with literals


ClearControls(AccountGrid);

// Throws exception: Control 'ComputerGrid' of type 'GridView'


// must be placed inside a form tag with runat=server.
// ComputerGrid.RenderControl(htmlWrite);

// Alternate to ComputerGrid.RenderControl above


System.Web.UI.HtmlControls.HtmlForm form
= new System.Web.UI.HtmlControls.HtmlForm();
Controls.Add(form);
form.Controls.Add(AccountGrid);
form.RenderControl(htmlWriter);

Response.Write(stringWriter.ToString());
Response.End();
}

private void ClearControls(Control control)


{
for (int i = control.Controls.Count - 1; i >= 0; i--)
{
ClearControls(control.Controls[i]);
}

if (!(control is TableCell))
{
if (control.GetType().GetProperty("SelectedItem") != null)
{
LiteralControl literal = new LiteralControl();
control.Parent.Controls.Add(literal);
try
{
literal.Text =
(string)control.GetType().GetProperty("SelectedItem"
).
GetValue(control, null);
}
catch
{}
control.Parent.Controls.Remove(control);
}
else if (control.GetType().GetProperty("Text") != null)
{
LiteralControl literal = new LiteralControl();
control.Parent.Controls.Add(literal);
literal.Text =
(string)control.GetType().GetProperty("Text").
GetValue(control, null);
control.Parent.Controls.Remove(control);
}
}
return;
}

Update: 7/30/2008

I previously noted that SetCacheability doesn’t seem to make a difference. Well, I was
right…until I deployed my code to a site behind SSL. As it turns out, in order for Internet
Explorer to open documents in Office (or any out-of-process, ActiveX document server),
Internet Explorer must save the file to the local cache directory and ask the associated
application to load the file by using IPersistFile::Load.

http://support.microsoft.com/default.aspx?scid=KB;EN-US;q316431&
If the file is not stored to disk, this operation fails. When Internet Explorer communicates
with a secure Web site through SSL, Internet Explorer enforces any no-cache request. If
the header or headers are present, Internet Explorer does not cache the file. Consequently,
Office cannot open the file.

RESOLUTION: Web sites that want to allow this type of operation should remove the
no-cache header or headers. In other words, comment out the following line of code
particularly if you are running under SSL:

Response.Cache.SetCacheability(System.Web.HttpCacheability.NoCache);

Additional Comments

if you are using an UpdatePanel, you may get a


System.WebForms.PageRequestManagerParserErrorException exception. The solution
is to add a PostBackTrigger and give it’s ControlID as the excel export button’s ID or you
can move your excel export button out side of the update panel. I verified both options
and they work great. I ultimately went with the former option as such:

...
</ContentTemplate>
<Triggers>
<asp:PostBackTrigger ControlID="btnExport" />
</Triggers>
</asp:UpdatePanel>
...

Per ASPAlliance, you may encounter issues a number of issues which require the
following solution. Check out the link (and the comments) for more details if you get
stuck. I only encountered #1 on the list.

1. You may get an exception which states your Control ‘Grid’ of type ‘GridView’
must be placed inside a form tag with runat=server. I overcame this by
dynamically adding a form to the page and then the GridView to the form before
RenderContent(). This solution came per the aforementioned post’s comments.
2. You may need to included the following page directive:
EnableEventValidation=”false”. I didn’t need to include this directive.
3. You may need Override the VerifyRenderingInServerForm Method. I didn’t need
to do so because I added my GridView control to a “mocked” form.

one can format the spreadsheet results in a generic manner by replacing all controls
within the GridView with Literals. This is reflected in the ClearControls() method
above. My prior implementation merely cleaned up the links associated with the sort
functionality tied to the sortable headers. This solution tackles all cells.

I found it on internet and its really good one you like it but it need some update so that it
can show grid line too.

Happy coding