miércoles, 19 de diciembre de 2007

Exportar un Datagrid a Excel (ASP.NET)

Asís García Chao

 

El control DataGrid de ASP.NET es muy útil para realizar listados que se puedan consultar en la web. Este control es de uso muy sencillo y permite paginar los resultados, ordenarlos por cualquier columna o editar sus celdas.

Imaginémonos la siguiente situación: hemos creado un listado para una aplicación en una Intranet y lo mostramos en una página aspx utilizando un DataGrid. Supongamos ahora que nos interesa trabajar con ese listado manejándolo con Excel. Una manera sencilla de conseguirlo es la que se presenta a continuación:

Supongamos lo siguiente:

  • El listado es generado por un control DataGrid llamado 'dataGrid' y se muestra en una página aspx
  • Todos los controles adicionales (Connection, DataAdapter...) ya han sido añadidos y están correctamente "configurados" (es decir, tenemos un listado web completamente operativo)



En la misma página añadiremos un botón llamado 'verExcel' que exportará el listado a Excel.

El código del evento Page_Load podría ser similar al que se muestra:


private void Page_Load(object sender, System.EventArgs e)
{
    sqlConnection.Open();
    DataSet dataSet = new DataSet();
    sqlDataAdapter.Fill(dataSet);

    dataGrid.DataSource = dataSet;
    dataGrid.DataBind();
}



Las dos últimas líneas de código son las que enlazan los datos de la consulta ejecutada por el DataAdapter (que serán los datos de nuestro listado) al DataGrid para mostrarlos en la página web.

Para exportar ese listado a Excel, lo único que necesitamos es cambiar el tipo MIME de la respuesta del servidor a "application/vnd.ms-excel". Cuando el navegador del cliente recibe la respuesta, si Excel está instalado, permite al usuario abrir directamente el fichero o guardarlo. El propio programa (Excel) se encarga de representar la tabla HTML que genera el DataGrid como una hoja Excel.

Lo que haremos será añadir código al evento de click del botón para cambiar el tipo MIME de la respuesta. Además, tendremos que controlar un par de cosillas para asegurar que todo funciona correctamente.


private void verExcel_Click(object sender, System.EventArgs e) {
    // No enviamos la respuesta hasta que hemos
    // terminado de procesar todo
    Response.Buffer = true;

    // Ponemos el tipo de la respuesta al valor adecuado
    Response.ContentType = "application/vnd.ms-excel";

    // Desactivamos el view state, ya que no lo necesitamos
    this.EnableViewState = false;

    // Desactivamos propiedades conflictivas
    dataGrid.AllowPaging = false;
    dataGrid.AllowSorting = false;

    // Enlazamos los datos de nuevo para reflejar
    // los cambios
    dataGrid.DataBind();


    // A continuación escribiremos el HTML que genera
    // el dataGrid en la respuesta para enviárselo al
    // cliente
    System.IO.StringWriter tw = new System.IO.StringWriter();
    HtmlTextWriter hw = new HtmlTextWriter(tw);

    dataGrid.RenderControl(hw);

    Response.Write(tw.ToString());

    // Enviamos los datos al cliente
    Response.End();
}



Unos comentarios acerca de este código:

En primer lugar, para evitar que el servidor comience a enviar datos al cliente antes de que se haya generado todo el contenido del DataGrid, utilizamos
Response.Buffer = true para indicar al servidor que espere a que realicemos todo el procesamiento necesario. Cuando hemos terminado, con Response.End() indicamos que la respuesta ya se puede enviar.

En segundo lugar, desactivamos el view state, ya que no vamos a mostrar datos en un formulario HTML y no necesitamos mantener el estado en el que se encuentran los controles de la página. También desactivamos la capacidad de paginación y de ordenamiento. Hay dos razones para hacer esto.

1.     Mostrar todo el listado en la hoja Excel, no sólo una página

2.     Evitar problemas en tiempo de ejecución. Me explico: el control DataGrid genera, para los enlaces que permiten ordenar o paginar el listado, código HTML que necesita estar dentro de un Web Form ASP.NET (esto es, tiene que estar entre los tags <form id="miform" runat="server"> y </form>). Cuando mostramos el DataGrid en el navegador como HTML en una página web, no hay problema. Pero cuando nos quedamos tan sólo con el HTML generado por el control DataGrid, como sucede en este ejemplo, obtendremos un error al ejecutar el código anterior, ya que el HTML generado por el DataGrid no se encuentra en un Web Form.



En tercer lugar, para garantizar que el DataGrid genera HTML sin los problemas anteriores, volvemos a enlazar los datos (esto se debería cambiar, ya que ahora mismo estamos enlazando los datos dos veces: una al cargar la página -evento Page_Load- y otra al hacer click).

Por último, utilizando un HtmlTextWriter y un StringWriter extraemos el HTML que genera el DataGrid (usando
dataGrid.RenderControl(hw) y lo escribimos en la respuesta.

Al ejecutar la página y pulsar sobre el botón, veremos un cuadro de diálogo en el que se nos informa de que nos vamos a descargar un fichero de tipo "Hoja de cálculo de Microsoft Excel" y se nos da la opción de abrirlo o guardarlo (según el navegador que estemos utilizando, la opción de abrir estará o no disponible). Si lo abrimos (sólo con el IE) veremos la hoja Excel embebida en el navegador. También podemos salvar la hoja a disco y abrirla con Excel.

Bueno, espero que haya quedado todo claro. Comentarios, dudas, críticas o sugerencias serán bienvenidos.

 


Autor: Asís García Chao

 

 

1 comentario:

Unknown dijo...

Hola, esta barbaro. me funciona la exportacion, pero solo veo los datos si selecciono "GUARDAR", si solo queiro ABRIR el excel muestra cualquier cosa. Mi navegador es IE 7.0. Me podes ayudar???