MVC Exportar Datos a .XLS “Excel Files”

Este truco es uno de los top10 en los foros de MSDN y sigue siendo una de aquellas cosas que no es fácil encontrar una documentación clara y adecuada.

Si hablamos desde la perspectiva de ASP.NET MVC esta tarea se nos simplifica muchísimo porque desde nuestro controlador podemos devolver directamente el contenido de un fichero como cualquier otro ActionResult que tengamos configurado. Para eso tenemos el método File que nos proporciona esa funcionalidad y no tenemos que utilizar directamente el objeto Response como nos pasaba con el clásico ASP.NET WebForms.

FileContentResult File(byte[] fileContents, string contentType)
FileContentResult File(byte[] fileContents, string contentType, string fileDownloadName)
FileStreamResult File(Stream fileStream, string contentType)
FileStreamResult File(Stream fileStream, string contentType, string fileDownloadName)
FilePathResult File(string fileName, string contentType)
FilePathResult File(string fileName, string contentType, string fileDownloadName)

Para este ejemplo utilizaré la sobrecarga que retorna un FileStreamResult porque lo que queremos hacer es:

Un servicio que recupere los datos de nuestro repositorio, serialice nuestra entidad del dominio en un XML directamente en memoria. Devuelva su contenido especificando que es un fichero Excel y el nombre del fichero que se utilizará para guardar.

Todo esto lo generará dinámicamente en memoria sin tener que tener el fichero Excel físicamente en nuestro servidor.

public ActionResult ObtenerMisEnviosXmlExcel()
{
    _productosServices = new ProductosServices();
    var stream = new MemoryStream();
    var serialicer = new XmlSerializer(typeof(List));

    //Cargo los datos
    List datos = _productosServices.GetProductos();

    //Lo transformo en un XML y lo guardo en memoria
   serialicer.Serialize(stream, datos);
   stream.Position = 0;

   //devuelvo el XML de la memoria como un fichero .xls
   return File(stream, "application/vnd.ms-excel", "Pedidos.xls");
}

Para poder serializar nuestra entidad del dominio utilizaremos la clase XmlSerializer que se encuentra en el namespace System.Xml.Serialization.

Cada vez que realicemos esta llamada nos devolverá el fichero Excel creado al vuelo con los datos recuperados de nuestro repositorio.

Una cosa que hay que tener en cuenta al realizar la serialización en XML, es que no es el formato estándar de Excel y tiene que abrir el fichero como datos XML. Eso implica que al abrir el fichero lance un par de avisos que son un poco incómodos más que otra cosa.

He estado probando diferentes librerías para crear ficheros Excel, pero todos te permiten montando el documento por programación, pero no montarlo automáticamente dependiendo de los datos cargados como es el caso del ejemplo anterior.

Si alguien conoce alguna librería que sea capaz de hacerlo directamente o tiene alguna experiencia parecida le invito a que la comparta para poder ampliar esta información y que nos sea de utilidad a todos.

Os recuerdo que también tenéis una entrada relacionada para generar un PDF al vuelo directamente desde una de nuestras vistas recuperando su HTML.

16 comentarios en “MVC Exportar Datos a .XLS “Excel Files”

  1. Marc Rubiño dijo:

    Todo el código es el que veis, solo cargo una lista en memoria y luego se envía al cliente serializado y especificando que el formato es de Excel.

    No hay nada más.

    Si me explicas el error puedo intentar ayudar a ver que te pasa.

  2. jose antonio dijo:

    pues es una duda primero
    en esta linea _productosServices = new ProductosServices();
    _productosServices es tu modelo o un controlador si me puedes esplicar esa linea es q de ahi surge mi duda y quizas mi error y gracias anticipadas

    • Marc Rubiño dijo:

      Claro ;-)
      _productosServices es el servicio que accede a mi lógica de negocio.
      Ese método devuelve una lista de productos de mi base de datos. Esos datos tienen la estructura de un modelo que se llama producto.
      En tu caso tendrías que recuperar los datos de tu negocio y cuando los tengas serializar los datos a XML y devolverlo desde el controlador que es donde está el código del ejemplo.

  3. jose antonio dijo:

    ok gracias Marc lo analizo y lo pongo en marcha porcierto igual tengo una dudita en el de pdf al vuelo pero te la hago por aquel foro y gracias encerio tiene 3 dias que estoy con esto saludos

  4. orlando dijo:

    hola marc esta muy bueno tue ejemplo pero si no es mucha molestia podrias hacer el ejemplo desde cero. mejor dicho desde archivo /crear nuevo poryecto… es que soy nuevo en este tema y me inetereza mucho saber hacer la generacion del excel.

  5. orlando dijo:

    hola marc muy inetesante tu aporte, pero podrias hacer este ejemplo desde cero. archivo/crear nuevo proyecto… soy nuevo en este tema y me interesa mucho parender a crear el excel.

  6. Fernando dijo:

    Funciona muy bien el código generado, aunque como el excel trata de interpretar el xml, al momento que se envía solo una fila con datos, no quedan identifica las columnas de cada dato.
    solo ocurre cuando es solo una fila, estoy intentado buscar una solucion, si alguien tiene alguna favor ayuda por favor.

  7. Sil dijo:

    Estoy utilizando MVC 4 y cuanod coloco la última linea me da el siguiente error:
    ‘System.IO.File’ is a ‘type’ but is used like a ‘variable’

  8. pepe dijo:

    Ojala me pudieran ayudar por favor. Hola que tal, tengo que pasar mis datos sql2008 a excel por web (App: Silverlight, C#,Vs2010,Ria services, Net4) hago una consulta asincronica y tengo mi Context.Datos, lo paso a un DataGrid (DGrid1.ItemSource = Context.Datos) y con un boton de Exportar cual seria el codigo q funcione, Mil Gracias (jmgyg@live.com.mx)

  9. Memo dijo:

    Que tal Marc al tratar de hacer la serializacion me marca un error como defines tu clase?
    asi tengo mi codigo:

    public ActionResult GenerarReporte(string modelo)
    {
    criteriosConsultaML criterios = new criteriosConsultaML();

    moduloCertificadosBM certificado = new moduloCertificadosBM();
    criterios = certificado.decodCriteriosConsulta(modelo);
    List generados = new List();
    GenerarFECBM generaFECBM = new GenerarFECBM();

    generados = generaFECBM.getGenerados(criterios);

    MemoryStream stream = new MemoryStream();
    XmlSerializer serializar = new XmlSerializer(typeof(List));

    serializar.Serialize(stream, generados);
    stream.Position = 0;

    return File(stream, «application/vnd.ms-excel», «reporte.xls»);
    }

    y el error que me sale es este:

    An exception of type ‘System.InvalidOperationException’ occurred in System.Xml.dll but was not handled in user code

    Additional information: There was an error reflecting type ‘System.Collections.Generic.List`1[BusinessModel.Models.certificadoPAMML]’.

    creo que el problema pudiera estar en como se define mi clase

    • Marc Rubiño dijo:

      Parece que sí, asegúrate que tu clase soporta la materialización en XML, porque tiene la pinta que tienes alguna propiedad que no lo soporta.

      Saludos

Deja un comentario