Hace ya bastante tiempo publiqué un pequeño "control" para exportar un Datagrid a Excel, esa vez decidí no publicar el código fuente debido a que éste tenía demasiados errores de programación -recién empezaba con .NET :-D .

Para mi sorpresa, al parecer este control fue utilizado por un gran número de personas y desde ese entonces he recibido varias consultas sobre el funcionamiento del mismo, algunas simples y otras imposibles de hacer por la forma como se hacía la exportación.

Luego de este breve repaso de la historia del mencionado control, quiero mostrar en resumen que hacía exactamente, pero esta vez utilizando ASP.NET 2.0.

El ejemplo más básico para exportar los contenidos de un GridView a Excel -en realidad sólo se envian las cabeceras necesarias para que el contenido que se envía sea reconocido como un archivo con formato Excel.

csharp:
StringBuilder sb = new StringBuilder();
StringWriter sw = new StringWriter(sb);
HtmlTextWriter htw = new HtmlTextWriter(sw);

GridView1.EnableViewState = false;
GridView1.RenderControl(htw);

Response.Clear();
Response.Buffer = true;
Response.ContentType = "application/vnd.ms-excel";
Response.AddHeader("Content-Disposition", "attachment;filename=data.xls");
Response.Charset = "UTF-8";
Response.ContentEncoding = Encoding.Default;
Response.Write(sb.ToString());
Response.End();

El problema con el anterior código, es que si el GridView contiene elementos que hace postback (HyperLink, LinkButton, Button, etc), el runtime de ASP.NET mandará un lindo error:

Server Error in '/GridView' Application.

Control 'GridView1' of type 'GridView' must be placed inside a form tag with runat=server.

Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.

Exception Details: System.Web.HttpException: Control 'GridView1' of type 'GridView' must be placed inside a form tag with runat=server.

Este error se produce porque este tipo de controles -los que realizan postback- hacen una llamada al método Page.VerifyRenderingInServerForm(), que como se muestra en la descripción del error, se asegura que el control que se le pase a ese método esté dentro de un elemento form con atributo runat="server".

Una forma de evitar este error, es crear una página al vuelo, que contenga un elemento Form y que éste a su vez contenga al GridView:

csharp:
StringBuilder sb = new StringBuilder();
StringWriter sw = new StringWriter(sb);
HtmlTextWriter htw = new HtmlTextWriter(sw);

Page page = new Page();
HtmlForm form = new HtmlForm();

GridView1.EnableViewState = false;

// Deshabilitar la validación de eventos, sólo asp.net 2
page.EnableEventValidation = false;

// Realiza las inicializaciones de la instancia de la clase Page que requieran los diseñadores RAD.
page.DesignerInitialize();

page.Controls.Add(form);
form.Controls.Add(GridView1);

page.RenderControl(htw);

Response.Clear();
Response.Buffer = true;
Response.ContentType = "application/vnd.ms-excel";
Response.AddHeader("Content-Disposition", "attachment;filename=data.xls");
Response.Charset = "UTF-8";
Response.ContentEncoding = Encoding.Default;
Response.Write(sb.ToString());
Response.End();

Esta última porción de código es la que está presente en el control, con algunas otras "características" más.

Si alguien desea un ejemplo del código mostrado en este artículo, que lo pida en los comentarios :) .

Archivos relacionados