Creo que este tema ya lo han visto en muchos blogs, como exportar de gridview a excel, PERO no tocan el tema de cuando es una consulta de mas de 13 mil registros (y eso que es poco) y que al momento de exportarlos te arroje un excel vació o corrupto, pues a mi me paso, por eso con este humilde post les voy a contar como solucione este problema (gracias a un gran amigo).
¿Que paso?
Bueno, me asignaron un proyecto en la cual necesitaban agregar unas columnas para mostrar unos datos que requería el cliente, si cambios, dije oh! sera algo rápido no me tomara mucho tiempo y lo cual fue cierta… hasta cierto punto… ya que todo funcionaba perfecto en mi maquina… hasta que subir los archivos actualizados al servidor de desarrollo… hicieron una pequeña consulta y BINGO! todo perfecto… hasta que… hicimos la consulta general para mostrar todos los registros, en el preview todo OK pero al momento de exportar el gridview a Excel PUM! no se podía abrir el excel «archivo dañado».
Los problemas
El problema era muy simple, exportar de gridview a excel no debería ser mucho problema… con mi poca experiencia que tengo con C# comencé a hacer pruebas locales cosa que todos me descargaron todos los registros pero al momento de subirlos a desarrollo todo se rompía: archivo dañado, descargaba un archivo con 0 bytes…
¿Como solucione el problema del gridview?
Despues de darle vueltas y vueltas a la manera de resolver este problema, exportar grandes cantidades de registro, pude hacerlo! yes!.
Ahora ¿como lo hice?, he creado 2 funciones y aca lo comparto para que si a alguno le ha pasado lo mismo tenga una solución rápida.
Primera función MExportar
Con la primera funcion llamaremos a nuestra Gridview, en mi caso ya tengo una funcion que hace esto y la convertimos en un DataTable.
C#
privatevoidMExportar(){try{GridView.AllowPaging=false;btnBuscar_Click(null,null);//Llamo a mi gridview con toda la dataDataTable dt=newDataTable(«Listado de Clientes»);// Asigno un nombre a mi DataTable//Agregamos los encabezados del Gridview al DataTableforeach(TableCell cell inGridView.HeaderRow.Cells){dt.Columns.Add(cell.Text);}//Agregamos las filas con los registrosforeach(GridViewRow row inGridView.Rows){dt.Rows.Add();for(vari=0;i<row.Cells.Count;i++){varlabel=row.Cells[i].FindControl(«label»+i)asLabel;if(label!=null)dt.Rows[dt.Rows.Count–1][i]=label.Text;}}//Comenzamos a agregar los parametros para generar nuestro ExcelvarlstrXml=this.XmLizeDt(dt,«»,«»,DateTime.Now.ToString(),«Listado de Clientes»);//Ejecutamos nuestra funcion para generar el excel(el codigo en el siguiente punto)//dt viene a ser la DataTable, Estructura de nuestro header para el archivo (por ahora no lo vamos a necesitar), Estructura de nuestro footer para el archivo (por ahora no lo vamos a necesitar), Fecha del reporte, Nombre de nuestra hojavarpath=Server.MapPath(«~/Download»)+«\\»;//Asignamos una carpeta temporal en donde se va a generar el archivovarfilename=DateTime.Now.Ticks.ToString()+«.xls»;//Generamos el nombre del archivo, que en este caso sera la fecha y hora//Explicar para que sirve esta parte seria algo laaaaaaaaaaargo, así que mejor les pongo el link de la documentación https://msdn.microsoft.com/es-es/library/2839d5h5(v=vs.110).aspxStringBuilder sb=newStringBuilder();StringWriter sw=newStringWriter(sb);HtmlTextWriter htw=newHtmlTextWriter(sw);//En esta parte creamos nuestro excel con los datos que nos genero la funcion XmLizeDthtw.Write(lstrXml);Response.Clear();Response.Buffer=true;System.IO.FileInfo toDownload=newSystem.IO.FileInfo(path+filename);Page.Response.AddHeader(«Content-Disposition»,«attachment; filename=»+toDownload.Name);Page.Response.ContentType=«application/octet-stream»;Page.Response.ContentEncoding=Encoding.UTF8;Response.Write(sb.ToString());Response.End();}catch(Exception lobjException){//Error}}
Esto seria todo para lo que va en la generación del excel.
Segunda función XmLizeDt
Con la siguiente función creamos la estructura de nuestro excel con los datos que generamos en la DataTable, el código es muy simple y eficiente.
C#
publicstringXmLizeDt(DataTable dt,stringbaseStructHeader,stringbaseStructFooter,stringfechaReporte,stringnombreTabla){#region DefaultStructintlintColCount=0;stringlstrXMLHeader=@»<?xml version=«»1.0«»?><?mso–application progid=«»Excel.Sheet«»?><Workbook xmlns=»«urn:schemas-microsoft-com:office:spreadsheet»«xmlns:o=»«urn:schemas-microsoft-com:office:office»«xmlns:x=»«urn:schemas-microsoft-com:office:excel»«xmlns:ss=»«urn:schemas-microsoft-com:office:spreadsheet»«xmlns:html=»«http://www.w3.org/TR/REC-html40»«><DocumentProperties xmlns=»«urn:schemas-microsoft-com:office:office»«><Author>Francisco Cordova</Author><LastAuthor>Francisco Cordova</LastAuthor><Created>2007-03-15T23:04:04Z</Created><Company>Wunderman Phantasia</Company><Version>12.00</Version></DocumentProperties><ExcelWorkbook xmlns=»«urn:schemas-microsoft-com:office:excel»«><WindowHeight>6795</WindowHeight><WindowWidth>8460</WindowWidth><WindowTopX>120</WindowTopX><WindowTopY>15</WindowTopY><ProtectStructure>False</ProtectStructure><ProtectWindows>False</ProtectWindows></ExcelWorkbook><Styles><Style ss:ID=»»Default»»ss:Name=»»Normal»»><Alignment ss:Vertical=»»Bottom»»/><Borders/><Font ss:FontName=»»Calibri»»x:Family=»»Swiss»»ss:Size=»»11″»ss:Color=»»#000000″»/><Interior/><NumberFormat/><Protection/></Style><Style ss:ID=»»s68″»><Font ss:FontName=»»Calibri»»x:Family=»»Swiss»»ss:Size=»»11″»ss:Color=»»#FFFFFF»»ss:Bold=»»1″»/><Interior ss:Color=»»#CC99FF»»ss:Pattern=»»Solid»»/></Style><Style ss:ID=»»s65″»><Font ss:FontName=»»Calibri»»x:Family=»»Swiss»»ss:Size=»»11″»ss:Color=»»#FFFFFF»»/><Interior ss:Color=»»#5B9BD5″»ss:Pattern=»»Solid»»/></Style></Styles><Worksheet ss:Name=»«REPLACENOMBRE»«><Table x:FullColumns=»«1»» x:FullRows=»«1»«>».Replace(«REPLACENOMBRE»,nombreTabla);stringlstrXMLFooter=@»</Table></Worksheet></Workbook>»;#endregionlintColCount=dt.Rows.Count–1;if(baseStructHeader==«»){baseStructHeader=lstrXMLHeader;}if(baseStructFooter==«»){baseStructFooter=lstrXMLFooter;}StringBuilder output=newStringBuilder();// Escribir encabezadosoutput.Append(baseStructHeader);//Escribir la cantidad de columnasforeach(DataColumn dc indt.Columns){output.AppendLine(@»<Column ss:Width=»«200»» />»);}//Encabezadosoutput.AppendLine(@»<Row ss:Index=»«2»«>»);foreach(DataColumn dc indt.Columns){output.AppendLine(@»<Cell ss:StyleID=»«s65»«><Data ss:Type=»«String»«>»+dc.ColumnName+«</Data></Cell>»);}output.AppendLine(«</Row>»);// Escribir datosforeach(DataRow item indt.Rows){intlintCounter=0;output.AppendLine(«<Row>»);foreach(objectvalue initem.ItemArray){if(dt.Columns[lintCounter].DataType==Type.GetType(«System.String»)){output.AppendLine(@»<Cell ><Data ss:Type=»«String»«><![CDATA[«+value+«]]></Data></Cell>»);}elseif(dt.Columns[lintCounter].DataType==Type.GetType(«System.Decimal»)){output.AppendLine(@»<Cell ><Data ss:Type=»«Number»«><![CDATA[«+value+«]]></Data></Cell>»);}else{output.AppendLine(@»<Cell ><Data ss:Type=»«String»«><![CDATA[«+value.ToString()+«]]></Data></Cell>»);}lintCounter++;}output.AppendLine(«</Row>»);}//Escribir pieoutput.Append(baseStructFooter);// Valor de retornoreturnoutput.ToString();}
Espero que les haya sido de utilidad, como lo fue para mi, no se olviden de compartir! 😀
Un gran agradecimiento a mi amigo Danny Siancas por la ayuda 🙂 te debo una caja de alfajores :D!!