Page 1 of 1

Espectacular clase ExcelWriterXML

Posted: Tue Feb 24, 2015 11:04 am
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

Re: Espectacular clase ExcelWriterXML

Posted: Tue Feb 24, 2015 1:07 pm
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

Re: Espectacular clase ExcelWriterXML

Posted: Fri Feb 27, 2015 12:20 pm
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

Re: Espectacular clase ExcelWriterXML

Posted: Fri Feb 27, 2015 12:30 pm
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

Re: Espectacular clase ExcelWriterXML

Posted: Mon Mar 02, 2015 12:10 pm
by jose_murugosa
Gracias, efectivamente a casi todas debi agregar hb y a dbfntx y otras rddntx etc..
Gran ayuda :)

Re: Espectacular clase ExcelWriterXML

Posted: Tue Mar 03, 2015 12:56 pm
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

Re: Espectacular clase ExcelWriterXML

Posted: Tue Mar 03, 2015 1:46 pm
by hmpaquito
Los errores son de enlazado. Yo creo que no estas enlazando la lib (contribs) donde viene incluida esa contribucion.

Re: Espectacular clase ExcelWriterXML

Posted: Tue Mar 03, 2015 2:18 pm
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?

Re: Espectacular clase ExcelWriterXML

Posted: Tue Mar 03, 2015 9:55 pm
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

Re: Espectacular clase ExcelWriterXML

Posted: Wed Mar 04, 2015 11:17 am
by MarioG
Gabo:
Muchas gracias; es lo que me faltaba

Re: Espectacular clase ExcelWriterXML

Posted: Wed Mar 04, 2015 12:25 pm
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

Re: Espectacular clase ExcelWriterXML

Posted: Wed Mar 04, 2015 6:00 pm
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