====== Descargar un fichero como excel ====== En todos los sitios web que consulto se dice que descargar un fichero como excel es muy sencillo: se carga el recordset y se devuelve como un cvs (todo separado por comillas y puntos y coma). Sin embargo, he realizado varias pruebas y no hay forma de hacerlo funcionar, así que no debe ser tan evidente. Siempre que pasa esto, lo que hago es abrir una línea de investigación. ===== Primer paso: ¿Qué es lo que se comunican entre el servidor y el navegador? ===== He cogido un sniffer de red y he visto qué es lo que contesta el servidor web cuando se descarga un archivo cvs. Es, ni más ni menos, que el contenido de este zip: {{:windows:http-excel-traf.zip|}} Ahora, si reproducimos **exactamente** el formato, hará lo mismo, digo yo, no??? ===== Segundo paso: hacer el desarrollo ==== <%@ Language=VBScript %> <% ' OJO!!!! ESTO NO FUNCIONA EN MODO DEPURACION ' OJO!!!! ESTO NO FUNCIONA EN MODO DEPURACION ' OJO!!!! ESTO NO FUNCIONA EN MODO DEPURACION ' OJO!!!! ESTO NO FUNCIONA EN MODO DEPURACION Response.Expires = 0 server.scriptTimeOut = 3600 ' una hora dim oTest dim rs set oTest = server.CreateObject("componente") set rs = oTest.hacerunaconsultaquedevuelvaunrecordset( "" ) dim oUtil dim sTable set oUtil = server.CreateObject("adWrap.util" ) sTable = oUtil.exportQuery( rs, 0 ) sContentType = "application/octet-stream" sFileName = "miconsulta.xls" Response.AddHeader "Content-Length", len(sTable) Response.ContentType = sContentType Response.AddHeader "Last-Modified", now Response.AddHeader "Accept-Ranges", "bytes" Response.AddHeader "Date", now ' cabecera para que el dialogo que aparezca en el navegador del cliente es ' "abrir" o "guardar como", en lugar de aparecer encastrado en una ventana del ' navegador. Response.AddHeader "Content-Disposition", "attachment;filename=""" & sFileName & """" Response.write sTable Response.End Y el código fuente de la funcion visual basic que convierte un recordset a tabla: ' nFormat = 1 - to HTML ....
' nFormat = 0 - to CVS data;data2;data3 Public Function exportQuery(ByVal rsIn As Object, _ Optional ByVal nFormat As Long = 1) As String Dim rsParam As adodb.Recordset Dim oUtil As Object Dim sql As String Dim functionName As String ' pon aquí el nombre de la funcion, para registro de errores functionName = "exportQuery" On Error GoTo catch Set oUtil = doNew("util") Dim sTableTemplate As String Dim sRowTemplate As String Dim sColumnTemplate As String Dim nColumn As Long Dim sTr As String Dim sTd As String Dim sTable As String Dim sFilteredSemicolon As String Dim sSeparator As String Select Case nFormat Case 0 ' para sacar un contenido cvs sTableTemplate = "$content$" sRowTemplate = "$content$" & vbCrLf sColumnTemplate = """$content_filtered$""" sSeparator = ";" Case 1 ' para sacar una tabla html sTableTemplate = "" & vbCrLf sTableTemplate = sTableTemplate & "$content$" & vbCrLf sTableTemplate = sTableTemplate & "
" & vbCrLf sRowTemplate = "" & vbCrLf sRowTemplate = sRowTemplate & "$content$" & vbCrLf sRowTemplate = sRowTemplate & "" & vbCrLf sColumnTemplate = "$content$" & vbCrLf sSeparator = "" Case Else ' para sacar un contenido cvs sTableTemplate = "$content$" sRowTemplate = "$content$" & vbCrLf sColumnTemplate = """$content_filtered$""" sSeparator = ";" End Select sTable = "" If Not rs_empty(rsIn) Then sTr = "" ' for every record nColumn = 0 sTd = "" Do While nColumn < rsIn.Fields.Count If nFormat = 1 Then sTd = concat(sTd, Replace(sColumnTemplate, "$content$", rsIn.Fields(nColumn).Name)) Else sFilteredSemicolon = Replace(rsIn.Fields(nColumn).Name, sSeparator, "") sTd = concat(sTd, Replace(sColumnTemplate, "$content_filtered$", sFilteredSemicolon), sSeparator) End If nColumn = nColumn + 1 Loop sTr = sTr & Replace(sRowTemplate, "$content$", sTd) rsIn.MoveFirst Do While Not rsIn.EOF ' for every record nColumn = 0 sTd = "" Do While nColumn < rsIn.Fields.Count If nFormat = 1 Then sTd = concat(sTd, Replace(sColumnTemplate, "$content$", rs_field(rsIn, nColumn, ""))) Else sFilteredSemicolon = Replace(rs_field(rsIn, nColumn, ""), ";", "") sTd = concat(sTd, Replace(sColumnTemplate, "$content_filtered$", sFilteredSemicolon), sSeparator) End If ' nFormat = 1 nColumn = nColumn + 1 Loop sTr = concat(sTr, Replace(sRowTemplate, "$content$", sTd)) rsIn.MoveNext Loop sTable = concat(sTable, Replace(sTableTemplate, "$content$", sTr)) End If ' not rs_empty(rsIn) final: doDel oUtil exportQuery = sTable Exit Function catch: Dim txtError As String txtError = functionName & ": " & Err.Description oUtil.EscribirLog txtError 'Devolvemos un resultado de error exportQuery = "" 'Destruimos los objetos doDel oUtil Err.Raise Err.Number, App.EXEName, txtError End Function ' performs the operation cBase = cBase & cIn ' adding a separator (cSep) if needed Private Function concat(ByVal cBase As String, ByVal cIn As String, Optional ByVal cSep As String = "") As String If Len(cBase) = 0 Then concat = cIn Else concat = cBase & cSep & cIn End If ' len(cBase) End Function