Espectacular clase ExcelWriterXML

Post Reply
hmpaquito
Posts: 1200
Joined: Thu Oct 30, 2008 2:37 pm

Espectacular clase ExcelWriterXML

Post by hmpaquito »

ExcelWriterXML (xlsxml.prg) [1] es una bonita clase para escribir archivos excel sin tener excel instalado. Codigo 100 % harbour.
Hay situaciones donde puede resultar muy practico. Me viene a la cabeza varias FiveWeb... con esta clase podrá generar documentos en excel sin necesidad de objeto OLE.
¿ Y que me dicen del nuevo FiveTouch que también podrá generar documentos excel bien desde Android, bien desde IOS ?

Además es super rápida... según he leído... nada que ver con la velocidad del Excel OLE.
Leyendo por ahí me he encontrado un ejemplo bastante completo... búsquenlo...


[1] https://github.com/harbour/core/blob/ma ... xlsxml.prg
gabo
Posts: 117
Joined: Tue Jan 03, 2006 8:31 pm

Re: Espectacular clase ExcelWriterXML

Post by gabo »

Code: Select all

//------------------------------------------------------------------------------
STATIC FUNCTION CrearHojaExcel( aProducs, aIgrediens, dFechaUno, dFechaDos )
//------------------------------------------------------------------------------
  LOCAL oXML, oSheet, nDias, aDias, nColMerge, lMesas, nLineas, cEmpresa, aItems
  LOCAL cFile, lPrimero, hDatos, nLenArray, cProducto, nn

  MsgWait("generando hoja de excel" )

  cFile:= GetFolderPersonal() + "\ReporteVentasDel.xml"

  aDias:= { "LUNES", "MARTES", "MIERCOLES", "JUEVES", "VIERNES", "SABADO", "DOMINGO" }

  oXML:= ExcelWriterXML():New(cFile)
  oXML:setOverwriteFile(.t.)
  oXML:showErrorSheet( .T. )

  oSheet:= oXML:addSheet('Ventas por Productos') // Crea la Hoja o Pestaña
  nLineas:= 0
 // Se Crean los estilos o formato de las celdas, cada estilo tiene un nombre con el cual se llamara despues al escribir una celda 
  WITH OBJECT oXML:addStyle( 'numberCan' )
       :alignHorizontal( "Right" )
       :alignVertical( "Center" )
       :setNumberFormat( "#,##0.0" )
       :setFontName('Calibri')
       :setFontSize(8)
  END WITH
  WITH OBJECT oXML:addStyle( 'numberRight' )
       :alignHorizontal( "Right" )
       :alignVertical( "Center" )
       :setNumberFormat( "#,##0.00" )
       :setFontName('Calibri')
       :setFontSize(8)
  END WITH
  WITH OBJECT oXML:addStyle('dias')
      :alignHorizontal('Center')
      :alignVertical('Center')
      :setFontName('Calibri')
      :setFontSize(8)
      :bgColor('#AEAAAA')
  END WITH
  WITH OBJECT oXML:addStyle('sucursal')
      :alignHorizontal('Center')
      :alignVertical('Center')
      :setFontName('Calibri')
      :setFontSize(12)
      :setFontBold()
      :bgColor('#E7E6E6')
  END WITH
  WITH OBJECT oXML:addStyle('mesas')
      :alignHorizontal('Center')
      :alignVertical('Center')
      :setFontName('Calibri')
      :setFontSize(8)
      :bgColor('#E7E6E6')
  END WITH
  WITH OBJECT oXML:addStyle('pedidos')
      :alignHorizontal('Center')
      :alignVertical('Center')
      :setFontName('Calibri')
      :setFontSize(8)
      :bgColor('#D6DCE4')
  END WITH
 // Titulos en la hoja
  oSheet:writeString(++nLineas,1,"REPORTE DE VENTAS")
  oSheet:writeString(++nLineas,1,"POR FECHA Y SUCURSALES DEL:")
  oSheet:writeString(++nLineas,1,"SUCURSAL DE PRUEBA")
  oSheet:writeString(++nLineas,1,DToC( Date() ) )

 // Se definen los anchos de las columnas
  oSheet:columnWidth( 1, 150 )
  FOR nDias:= 1 TO 28
      oSheet:columnWidth( 1+nDias, 42 )
  NEXT
  ++nLineas

  // Se escribe en una celda usando el estilo "pedidos"
  oSheet:writeString(++nLineas,1,"PRODUCTOS", 'pedidos' )
 // Se Escribe en las celdas usando el estilo "dias"
  nColMerge:= 2
  FOR nDias:= 1 TO 7
      oSheet:writeString( nLineas, nColMerge, aDias[nDias], 'dias' )
      nColMerge+=4
  NEXT
 // Celdas combinadas cellmerge( nRow, nCol, nNumeroDeColumnasACombinar, nNumeroDeFilasACombinar )
  oSheet:cellMerge( nLineas, 1, 0, 1 )
  oSheet:cellMerge( nLineas, 2, 3, 0 )
  oSheet:cellMerge( nLineas, 6, 3, 0 )
  oSheet:cellMerge( nLineas,10, 3, 0 )
  oSheet:cellMerge( nLineas,14, 3, 0 )
  oSheet:cellMerge( nLineas,18, 3, 0 )
  oSheet:cellMerge( nLineas,22, 3, 0 )
  oSheet:cellMerge( nLineas,26, 3, 0 )

  lMesas:= .T.
  ++nLineas
  nColMerge:= 2
  FOR nDias:= 1 TO 14
      IF lMesas
         oSheet:writeString( nLineas,nColMerge,"MESAS",'mesas')
      ELSE
         oSheet:writeString( nLineas,nColMerge,"DOMICILIO",'pedidos')
      ENDIF
      lMesas:= !lMesas
      nColMerge+=2
  NEXT

  oSheet:cellMerge( nLineas, 2, 1, 0 )
  oSheet:cellMerge( nLineas, 4, 1, 0 )
  oSheet:cellMerge( nLineas, 6, 1, 0 )
  oSheet:cellMerge( nLineas, 8, 1, 0 )
  oSheet:cellMerge( nLineas,10, 1, 0 )
  oSheet:cellMerge( nLineas,12, 1, 0 )
  oSheet:cellMerge( nLineas,14, 1, 0 )
  oSheet:cellMerge( nLineas,16, 1, 0 )
  oSheet:cellMerge( nLineas,18, 1, 0 )
  oSheet:cellMerge( nLineas,20, 1, 0 )
  oSheet:cellMerge( nLineas,22, 1, 0 )
  oSheet:cellMerge( nLineas,24, 1, 0 )
  oSheet:cellMerge( nLineas,26, 1, 0 )
  oSheet:cellMerge( nLineas,28, 1, 0 )

  ++nLineas
  lMesas:= .T.
  nColMerge:= 2
  FOR nDias:= 1 TO 28
      IF lMesas
         oSheet:writeString( nLineas,nColMerge,"CANTIDAD",'mesas')
      ELSE
         oSheet:writeString( nLineas,nColMerge,"TOTAL",'mesas')
      ENDIF
      lMesas:= !lMesas
      ++nColMerge
  NEXT

  cEmpresa := "@"
  cProducto:= "@"
  lPrimero:= .T.
  FOR EACH aItems IN aProducs
      IF aItems[1] != cEmpresa
         ++nLineas
         IF !lPrimero
            ++nLineas
         ENDIF
         oSheet:writeString( nLineas,1, aItems[1],'sucursal' )
         cEmpresa:= aItems[1]
         lPrimero:= .F.
      ENDIF
      IF aItems[3] != cProducto
         ++nLineas
         oSheet:writeString( nLineas,1, aItems[4] )
         cProducto:= aItems[3]
      ENDIF
     // Se escriben Celdas Numericas <ojo> segun el tipo de dato de la celda se usa el metodo correspondiente. 
     // revisar fuentes de la lib para demas tipos de datos
     // oSheet:writeString
     // oSheet:writeNumber
      DO CASE
         CASE DoW( aItems[2] ) == 2 // "Lunes"    // 2
              oSheet:writeNumber( nLineas,2, aItems[5], 'numberCan' )
              oSheet:writeNumber( nLineas,3, aItems[6], 'numberRight' )
              oSheet:writeNumber( nLineas,4, aItems[7], 'numberCan' )
              oSheet:writeNumber( nLineas,5, aItems[8], 'numberRight' )

         CASE DoW( aItems[2] ) == 3 // "Martes"   // 3
              oSheet:writeNumber( nLineas,6, aItems[5], 'numberCan' )
              oSheet:writeNumber( nLineas,7, aItems[6], 'numberRight' )
              oSheet:writeNumber( nLineas,8, aItems[7], 'numberCan' )
              oSheet:writeNumber( nLineas,9, aItems[8], 'numberRight' )

         CASE DoW( aItems[2] ) == 4 // "Miércoles" // 4
              oSheet:writeNumber( nLineas,10, aItems[5], 'numberCan' )
              oSheet:writeNumber( nLineas,11, aItems[6], 'numberRight' )
              oSheet:writeNumber( nLineas,12, aItems[7], 'numberCan' )
              oSheet:writeNumber( nLineas,13, aItems[8], 'numberRight' )

         CASE DoW( aItems[2] ) == 5 // "Jueves"   // 5
              oSheet:writeNumber( nLineas,14, aItems[5], 'numberCan' )
              oSheet:writeNumber( nLineas,15, aItems[6], 'numberRight' )
              oSheet:writeNumber( nLineas,16, aItems[7], 'numberCan' )
              oSheet:writeNumber( nLineas,17, aItems[8], 'numberRight' )

         CASE DoW( aItems[2] ) == 6 // "Viernes"  // 6
              oSheet:writeNumber( nLineas,18, aItems[5], 'numberCan' )
              oSheet:writeNumber( nLineas,19, aItems[6], 'numberRight' )
              oSheet:writeNumber( nLineas,20, aItems[7], 'numberCan' )
              oSheet:writeNumber( nLineas,21, aItems[8], 'numberRight' )

         CASE DoW( aItems[2] ) == 7 // "Sábado"  // 7
              oSheet:writeNumber( nLineas,22, aItems[5], 'numberCan' )
              oSheet:writeNumber( nLineas,23, aItems[6], 'numberRight' )
              oSheet:writeNumber( nLineas,24, aItems[7], 'numberCan' )
              oSheet:writeNumber( nLineas,25, aItems[8], 'numberRight' )

         CASE DoW( aItems[2] ) == 1 // "Domingo" // 1
              oSheet:writeNumber( nLineas,26, aItems[5], 'numberCan' )
              oSheet:writeNumber( nLineas,27, aItems[6], 'numberRight' )
              oSheet:writeNumber( nLineas,28, aItems[7], 'numberCan' )
              oSheet:writeNumber( nLineas,29, aItems[8], 'numberRight' )
      END CASE
  NEXT

  oXML:writeData( cFile )
  WaitOff()

  wapi_ShellExecute( 0, 'open', cFile, , 0, 0 )

 RETURN NIL
 
Saludos
User avatar
jose_murugosa
Posts: 943
Joined: Mon Feb 06, 2006 4:28 pm
Location: Uruguay
Contact:

Re: Espectacular clase ExcelWriterXML

Post by jose_murugosa »

Estoy haciendo mis primera aproximación a harbour, precisamente con esta clase, y me dice que debo compilar RTL.lib, esta lib la tengo en xharbour, pero no la encuentro en harbour... alguien me podría decir como obtenerla?

Gracias desde ya
Saludos/Regards,
José Murugosa
FWH + Harbour + Bcc7. Una seda!
hmpaquito
Posts: 1200
Joined: Thu Oct 30, 2008 2:37 pm

Re: Espectacular clase ExcelWriterXML

Post by hmpaquito »

Creo que en harbour es hbrtl.lib.
En harbour fueron "prefijadas" muchas lib con "hb".
Lo mejor en _ es tener a mano un .mak que construya correctamente e ir viendo como se llaman.

saludos
User avatar
jose_murugosa
Posts: 943
Joined: Mon Feb 06, 2006 4:28 pm
Location: Uruguay
Contact:

Re: Espectacular clase ExcelWriterXML

Post by jose_murugosa »

Gracias, efectivamente a casi todas debi agregar hb y a dbfntx y otras rddntx etc..
Gran ayuda :)
Saludos/Regards,
José Murugosa
FWH + Harbour + Bcc7. Una seda!
User avatar
MarioG
Posts: 1356
Joined: Fri Oct 14, 2005 1:28 pm
Location: Resistencia - Chaco - AR

Re: Espectacular clase ExcelWriterXML

Post by MarioG »

Hola;
estoy en mis primeros paso con Harbour
he intentado compilar el sample que dejaron. Al compilar me arroja los siguientes errores
--------------------Configuración: pru32 - Debug--------------------
Harbour 3.2.0dev (r1406161338)
Copyright (c) 1999-2014, http://harbour-project.org/
Borland C++ 5.82 for Win32 Copyright (c) 1993, 2005 Borland
TextXLM0.c:
Turbo Incremental Link 5.69 Copyright (c) 1997-2005 Borland
Error: Unresolved external '_HB_FUN_EXCELWRITERXML_STYLE' referenced from D:\FUEN32\PRU32\DEBUG\XLSXLM.OBJ
Error: Unresolved external '_HB_FUN_EXCELWRITERXML_SHEET' referenced from D:\FUEN32\PRU32\DEBUG\XLSXLM.OBJ
Error: Unresolved external '_HB_FUN_WAITOFF' referenced from D:\FUEN32\PRU32\DEBUG\TEXTXLM0.OBJ
testmet.EXE - 3 error(es), 0 advertencia(s)
Que estoy haciendo mal?
gracias
Resistencia - "Ciudad de las Esculturas"
Chaco - Argentina
hmpaquito
Posts: 1200
Joined: Thu Oct 30, 2008 2:37 pm

Re: Espectacular clase ExcelWriterXML

Post by hmpaquito »

Los errores son de enlazado. Yo creo que no estas enlazando la lib (contribs) donde viene incluida esa contribucion.
User avatar
MarioG
Posts: 1356
Joined: Fri Oct 14, 2005 1:28 pm
Location: Resistencia - Chaco - AR

Re: Espectacular clase ExcelWriterXML

Post by MarioG »

Paquito, gracias por responder
Entre mis libs no tengo la contribs
Ingresé en Harbour and xHarbour builds, la busco, pero al menos en forma separada no viene
Por otro lado aclaro que yo hice un testxlm, del ejemplo aqui dejado, y lo compile junto a xlsxlm.prg
alguna sugerencia?
Resistencia - "Ciudad de las Esculturas"
Chaco - Argentina
gabo
Posts: 117
Joined: Tue Jan 03, 2006 8:31 pm

Re: Espectacular clase ExcelWriterXML

Post by gabo »

Mario
Los fuentes se encuentran en
\Harbour\extras\hbxlsxml
Si no puedes crear la lib agrega los fuentes a tu proyecto de ejemplo
\Harbour\extras\hbxlsxml\xlsxml.prg
\Harbour\extras\hbxlsxml\xlsxml_s.prg
\Harbour\extras\hbxlsxml\xlsxml_y.prg

Saludos
User avatar
MarioG
Posts: 1356
Joined: Fri Oct 14, 2005 1:28 pm
Location: Resistencia - Chaco - AR

Re: Espectacular clase ExcelWriterXML

Post by MarioG »

Gabo:
Muchas gracias; es lo que me faltaba
Resistencia - "Ciudad de las Esculturas"
Chaco - Argentina
User avatar
MarioG
Posts: 1356
Joined: Fri Oct 14, 2005 1:28 pm
Location: Resistencia - Chaco - AR

Re: Espectacular clase ExcelWriterXML

Post by MarioG »

Gente;
he probado los samples de core/extras/hbxlsxml/tests
En particular el sample3

Code: Select all

PROCEDURE Main()

   LOCAL xml, sheet1, format4

   xml := ExcelWriterXML():New( "my file.xml" )

   MsgWait("generando hoja example3" )

   sheet1 := xml:addSheet( "Plan 1" )

   format4 := xml:addStyle( "my style" )
   format4:setFontSize( 20 )
   format4:setFontColor( "yellow" )
   format4:bgColor( "blue" )

   sheet1:columnWidth( 1, 150 )
   sheet1:columnWidth( 2, 150 )
   sheet1:columnWidth( 3, 150 )

   // Si se altera el orden da error
   sheet1:writeString( 1, 1, "celula 1_1", format4 )
   sheet1:writeString( 1, 3, "celula 1_3", format4 )
   sheet1:writeString( 2, 1, "celula 2_1", format4 )
   sheet1:writeString( 2, 2, "celula 2_2", format4 )
   sheet1:writeString( 2, 3, "celula 2_3", format4 )
   sheet1:cellMerge( 1, 1, 1, 0 )      // No pone en el centro como lo hace Excel
/*
#if 0
   sheet1:writeString( 1, 2, "celula 1_2", format4 )
#endif
*/
   xml:writeData( "example3.xml" )
   wapi_ShellExecute( 0, 'open', "example3.xml", , 0, 0 )

   RETURN
Donde dejo el comentario "Si se altera el orden da error"
En el original esta:

Code: Select all

    sheet1:writeString( 2, 3, "celula 2_3", format4 )
   sheet1:writeString( 2, 2, "celula 2_2", format4 )
   sheet1:writeString( 2, 1, "celula 2_1", format4 )
 
De esta forma al abrir la hoja da error de exportación HTML
Lo otro que detecto es que al hacer el Merge, no centra el texto, como por defecto lo hace Excel
Uso Excel 2010
Resistencia - "Ciudad de las Esculturas"
Chaco - Argentina
gabo
Posts: 117
Joined: Tue Jan 03, 2006 8:31 pm

Re: Espectacular clase ExcelWriterXML

Post by gabo »

Mario

Code: Select all

//Sintaxis
cellmerge( nRow, nCol, nNumeroDeColumnasACombinar, nNumeroDeFilasACombinar )
//Tu Codigo
sheet1:cellMerge( 1, 1, 1, 0 )  // No pone en el centro como lo hace Excel
 
Saludos
Post Reply