Page 1 of 5

Felices reyes!

PostPosted: Fri Jan 06, 2017 12:02 pm
by Carlos Mora
Hola gente,

¿Habeis sido buenos este año? Seguro que sí. Yo no tengo quejas, siempre he recibido mucha ayuda de los compañeros y creo que os mereceis muchos regalos.

Con el permiso del "jefe", les comparto a modo de regalo de reyes una clase que suplanta en un porcentaje alto a la TPrinter para la generación de PDFs, usando como motor la HaruPdf que tan buenos resultados da.

No requiere conocer la Haru, esta clase "habla" en términos de TPrinter con algunas excepciones, como son los FONTs, que necesitan cierta gestión, y la cuestión de seguridad del documento PDF que no tiene equivalente en la TPrinter. Tampoco maneja, al menos de momento, BMPs, solo gestiona PNGs y JPGs. A pesar de este inconveniente, la gestión de imágenes es muy eficiente. Por ejemplo, si usamos una imágen como "marca de agua" en todas las hojas del pdf, la clase almacena la imagen de forma indexada y hace referencia a esa indexada en cada página, con lo que se evita que la imagen se repita dentro del documento.
Tambien puede usarse en programas en modo consola.

La clase está disponible en https://bitbucket.org/carlos_mora/pdfprinter, incluye el 100% incluído el proyecto de XEdit para generar la lib.

En un rato subiré un ejemplo completo de uso tal como lo vengo explotando.

Todas las correciones o sugerencias son bienvenidas. Espero que resulte útil y que le saqueis provecho.

Re: Felices reyes!

PostPosted: Fri Jan 06, 2017 12:42 pm
by Carlos Mora
Ejemplo de código. Inluye el uso de código de barras e imágenes.

Code: Select all  Expand view

/*
 * Proyecto: FacturaE
 * Fichero: TRecibos.prg
 * Descripción: Modelo de Recibos
 * Autor: Carlos Mora
 * Fecha: 27/03/2016
 */

#include 'harupdf.ch'
#include 'hbclass.ch'
#include 'common.ch'

#xcommand TEXT INTO <v> => #pragma __cstream|<v>:=%s
#xcommand TEXT INTO <v> ADDITIVE => #pragma __cstream|<v>+=%s

CLASS TRecibo
   DATA cCUIT     INIT '30666666666'
   DATA NOrigen   INIT 0
   DATA PtoVenta  INIT '0004'
   DATA CbteTipo  INIT '009'
   DATA Concepto  INIT '1'
   DATA DocTipo   INIT '96'
   DATA DocNro
   DATA Numero
   DATA CbteFch   INIT Date()
   DATA ImpTotal  INIT 0
   DATA ImpTotConc INIT 0
   DATA ImpNeto    INIT 0
   DATA ImpOpEx    INIT 0
   DATA ImpTrib    INIT 0
   DATA ImpIVA     INIT 0
   DATA FchServDesde INIT '0'
   DATA FchServHasta INIT '0'
   DATA FchVtoPago   INIT '0'
   DATA MonId        INIT 'PES'
   DATA MonCotiz     INIT '1'
   DATA Nombre       INIT '1'
   DATA aTributos
   DATA aIva
   DATA CAE
   DATA CAEVto
   DATA Resultado
   DATA Reproceso
   DATA Code
   DATA Msg

   CONSTRUCTOR New()
   METHOD Imprime()

ENDCLASS

METHOD New()
   ::aTributos:= Array()
   ::aIva:= Array()
RETURN Self


METHOD Imprime()
   LOCAL oPrint, i, nOffset
   LOCAL oFontBold, oFontRed, oFontBig, oFont, oFontMin, oFontPrint, oFontPrintR, oFont2of5
   LOCAL aConceptos, aObservaciones
   LOCAL cLetras:= 'Pesos ' + EnLetras(::ImpTotal)
   LOCAL cNombrePdf

   oPrint := THaruPdf():New()
   SetMode( 30, 80 )

   oPrint:SetCompression( HPDF_COMP_ALL )
   // oPrint:SetPage(HPDF_PAGE_SIZE_LEGAL)
   GetHaruFontList()
   HaruAddFont( 'Arial Black', 'ariblk.ttf' )
   HaruAddFont( 'i2of5txt', 'i2of5txt.ttf', .T. )
   oFontBold := oPrint:DefineFont( 'Arial Black', 10 )
   oFontBig := oPrint:DefineFont( 'Arial Black', 16 )
   oFont := oPrint:DefineFont( 'Helvetica', 10 )
   oFontRed := oPrint:DefineFont( 'Helvetica', 8 )
   oFontMin := oPrint:DefineFont( 'Helvetica', 6 )
   oFontPrint := oPrint:DefineFont( 'Courier', 10 )
   oFontPrintR := oPrint:DefineFont( 'Courier', 8 )
   oFont2of5 := oPrint:DefineFont( 'i2of5txt', 14, .T. )

   oPrint:StartPage()


   // Bloque del Numero
   FOR nOffset := 0 TO 14.85 STEP 14.85
      WITH OBJECT oPrint
         // Datos Empresa
         :CmSayBitmap( nOffset + 0.5, 1, 'Logo3.png', 3, 3 )
         :CmSay( nOffset + 1.65, 7.0, 'Av. Colón 251', oFont, 5.0,,, HPDF_TALIGN_CENTER )
         :CmSay( nOffset + 2.0, 7.0, 'Tel.: (0351) 4251793 / 4236023', oFont, 5.0,,, HPDF_TALIGN_CENTER )
         :CmSay( nOffset + 2.35, 7.0, '4254733 / 4222367', oFont, 5.0,,, HPDF_TALIGN_CENTER )
         :CmSay( nOffset + 2.7, 7.0, 'C.P.: 5000 - CORDOBA', oFont, 5.0,,, HPDF_TALIGN_CENTER )
         :CmSay( nOffset + 3.7, 3.0, 'I.V.A. RESPONSABLE INSCRIPTO', oFont )

         // Tipo de Comprobante
         :CmRect( nOffset + 0.5, 10, nOffset + 1.5, 11, 0.1 )
         :CmSay( nOffset + 0.6, 10.3, 'B', oFontBig, , , , 0 )
         :CmSay( nOffset + 1.6, 10, 'Código 09', oFontMin, , , , 0 )

         // Numero de comprobante, fecha, inscripciones
         :CmRect( nOffset + 0.5, 13.5, nOffset + 4.0, 20.5, 0.1 )
         :CmLine( nOffset + 2.6, 13.5, nOffset + 2.6, 20.5 )
         :CmRect( nOffset + 1.6, 16.5, nOffset + 2.5, 20.4 )
         :CmSay( nOffset + 1.8, 17.4, DToC( Date() ), oFontPrint )
         :CmSay( nOffset + 0.6, 16.0, 'R E C I B O', oFontBold )
         :CmSay( nOffset + 1.0, 15.2, 'Nº '+::PtoVenta+'-'+StrZero(Val(::Numero),8), oFontBold )
         :CmSay( nOffset + 1.8, 14.0, 'CORDOBA', oFont )

         :CmSay( nOffset + 2.7, 13.8, 'C.U.I.T.: 30-66666666-6', oFontRed )
         :CmSay( nOffset + 3.0, 13.8, 'ING.BRUTOS: 250777777', oFontRed )
         :CmSay( nOffset + 3.3, 13.8, 'C. e I. MUNICIPAL CBA: 30-66666666-6', oFontRed )
         :CmSay( nOffset + 3.6, 13.8, 'Inicio Actividades: 07/03/1994', oFontRed )
         :CmSay( nOffset + 2.7, 20.1, If( nOffset == 0,'ORIGINAL', 'DUPLICADO' ), oFontBold,,,, HPDF_TALIGN_RIGHT )

         // Datos del Cliente
         :CmRect( nOffset + 4.2, 0.5, nOffset + 5, 20.5 )
         :CmSay( nOffset + 4.4, 1.0, 'SEÑOR:', oFont )
         :CmSay( nOffset + 4.35, 2.6, ::Nombre, oFontPrint )

         // Categoria IVA del Cliente
         :CmRect( nOffset + 5.0, 0.5, nOffset + 5.8, 20.5 )

         :CmSay( nOffset + 5.2, 1.0, 'A CONSUMIDOR FINAL', oFont )
         :CmRect( nOffset + 5.1, 5.0, nOffset + 5.7, 5.7 )
         :CmSay( nOffset + 5.15, 5.35, 'X', oFontPrint, 0.7,,, HPDF_TALIGN_CENTER )

         :CmSay( nOffset + 5.2, 7.0, 'EXENTO', oFont )
         :CmRect( nOffset + 5.1, 9.0, nOffset + 5.7, 9.7 )
         // :CmSay( nOffset + 5.15, 9.35, 'X', oFontPrint, 0.7,,, HPDF_TALIGN_CENTER )

         :CmSay( nOffset + 5.2, 12.0, 'C.U.I.T.', oFont )
         :CmRect( nOffset + 5.1, 13.5, nOffset + 5.7, 20.0 )
         // :CmSay( nOffset + 5.15, 14, '20-17078759-6', oFontPrint )

         // Importe en letras
         :CmSay( nOffset + 5.9, 1.0, 'Recibimos la suma de', oFont )
         :CmSay( nOffset + 5.9, 4.8, PadR( AllTrim(MemoLine(cLetras,50,1)), 65, '/'), oFontPrint )
         :CmSay( nOffset + 6.4, 4.8, PadR( AllTrim(MemoLine(cLetras,50,2)), 65, '/'), oFontPrint )

         // Forma de Pago
         :CmRect( nOffset + 7.0, 0.5, nOffset + 8.3, 20.5 )

         :CmRect( nOffset + 7.1, 1.0, nOffset + 7.7, 1.6 )
         :CmSay( nOffset + 7.2, 1.8, 'EFECTIVO', oFontRed )

         :CmRect( nOffset + 7.1, 3.8, nOffset + 7.7, 4.4 )
         IF Empty( Recibos->Banco )
            :CmSay( nOffset + 7.15, 1.3, 'X', oFontPrint, 0.7,,, HPDF_TALIGN_CENTER )
         ELSE
            :CmSay( nOffset + 7.15, 4.1, 'X', oFontPrint, 0.7,,, HPDF_TALIGN_CENTER )
         ENDIF
         :CmSay( nOffset + 7.2, 4.6, 'CON CHEQUE Nº', oFontRed )
         IF !Empty( Recibos->Banco )
            :CmSay( nOffset + 7.2, 7.0, LTrim(Str(Recibos->Cheque)), oFontPrintR )
         ENDIF

         :CmSay( nOffset + 7.2, 9.2, 'C/BANCO', oFontRed )
         IF !Empty( Recibos->Banco )
            :CmSay( nOffset + 7.2, 10.6, Recibos->Banco, oFontPrintR )
         ENDIF

         :CmSay( nOffset + 7.2, 14.5, 'SUC', oFontRed )
         IF !Empty( Recibos->Banco )
            :CmSay( nOffset + 7.2, 15.2, Recibos->Sucursal, oFontPrintR )
         ENDIF

         :CmSay( nOffset + 7.2, 18.8, 'sujeto a', oFontRed )
         :CmSay( nOffset + 7.8,  1.0, 'acreditación, el que una vez hecho efectivo se aplicará al pago de los conceptos detallados', oFontRed )

         :CmRect( nOffset + 8.5, 0.5, nOffset + 9.8, 20.5 )
         :CmLine( nOffset + 8.9, 0.5, nOffset + 8.9, 20.5 )
         :CmLine( nOffset + 8.5, 4.5, nOffset + 9.8, 4.5 )
         :CmSay( nOffset + 8.55, 2.5, 'Nº Factura', oFontRed, 0.7,,, HPDF_TALIGN_CENTER )
         IF Recibos->NCredito > 0
            :CmSay( nOffset + 9.1, 2.5, 'X 0001-'+StrZero(Creditos->Factura,8), oFontPrint, 0.7,,, HPDF_TALIGN_CENTER )
         ENDIF
         :CmLine( nOffset + 8.5, 8.5, nOffset + 9.8, 8.5 )
         :CmSay( nOffset + 8.55, 6.5, 'Nº Código', oFontRed, 0.7,,, HPDF_TALIGN_CENTER )
         :CmSay( nOffset + 9.1, 6.5, Recibos->CodOrg, oFontPrint, 0.7,,, HPDF_TALIGN_CENTER )
         :CmLine( nOffset + 8.5, 12.5, nOffset + 9.8, 12.5 )
         :CmSay( nOffset + 8.55, 10.5, 'Nº Crédito', oFontRed, 0.7,,, HPDF_TALIGN_CENTER )
         IF Recibos->NCredito > 0
            :CmSay( nOffset + 9.1, 10.5, Str(Creditos->NCredito,5), oFontPrint, 0.7,,, HPDF_TALIGN_CENTER )
         ENDIF
         :CmLine( nOffset + 8.5, 16.5, nOffset + 9.8, 16.5 )
         :CmSay( nOffset + 8.55, 14.5, 'Nº Cuota', oFontRed, 0.7,,, HPDF_TALIGN_CENTER )
         :CmSay( nOffset + 9.1, 14.5, If( Recibos->EsAdelanto,'Anticipo',LTrim(Str(Recibos->NroCuota))+' de '+ LTrim(Str(Creditos->Cuotas))), oFontPrint, 0.7,,, HPDF_TALIGN_CENTER )
         :CmSay( nOffset + 8.55, 18.5, 'Vencimiento Cuota', oFontRed, 0.7,,, HPDF_TALIGN_CENTER )
         :CmSay( nOffset + 9.1, 18.5, DtoC(Recibos->FechaVto), oFontPrint, 0.7,,, HPDF_TALIGN_CENTER )

         // Conpceptos
         :CmSay( nOffset + 10, 1.0, 'Descripción del cobro', oFontRed )
         aConceptos := { { 'Cuota Capital', Recibos->Capital } ;
            , { 'Cuota Intereses',     Recibos->Intereses } ;
            , { 'Intereses Moratorios',  Recibos->Punitorios } ;
            , { 'Gastos Recuperados',  Recibos->Gastos } ;
            , { 'Anticipos a cuenta', Recibos->Anticipos } ;
            , { 'Descuento de Intereses', Recibos->Descuento } ;
            , { 'Otros',     0.00 } ;
            }
         FOR i := 1 TO Len( aConceptos )
            :CmSay( nOffset + 10.5 + ( i - 1 ) * 0.43, 1.0, aConceptos[ i ][ 1 ], oFontRed )
            :CmRect( nOffset + 10.4 + ( i - 1 ) * 0.43, 5.0, nOffset + 10.4 + ( i ) * 0.43, 8.5 )
            :CmSay( nOffset + 10.4 + ( i - 1 ) * 0.43, 8.3, Str( aConceptos[ i ][ 2 ],12,2 ), oFontPrintR,,,, HPDF_TALIGN_RIGHT )
         NEXT
         :CmSay( nOffset + 10.5 + ( i - 1 ) * 0.43, 1.0, 'TOTAL', oFontBold )
         :CmRect( nOffset + 10.4 + ( i - 1 ) * 0.43, 5.0, nOffset + 10.6 + ( i ) * 0.43, 8.5, 1.5 )
         :CmSay( nOffset + 10.5 + ( i - 1 ) * 0.43, 8.3, Str( ::ImpTotal,12,2 ), oFontBold,,,, HPDF_TALIGN_RIGHT )

         // Observaciones
         aObservaciones := { 'Recuerde que para renovar su crédito' ;
            , 'deberá presentar su último Recibo de Haberes,' ;
            , 'y una boleta de servicios reciente.' ;
            }
         :CmRect( nOffset + 10.4, 8.9, nOffset + 12.9, 16.5, 0.1 )
         FOR i := 1 TO Len( aObservaciones )
            :CmSay( nOffset + 10.5 + ( i - 1 ) * 0.43, 9.0, aObservaciones[ i ], oFontPrintR )
         NEXT

         // Sello
         :CmRect( nOffset + 10.4, 16.9, nOffset + 14.3, 20.5 )
         :CmSay( nOffset + 10.5, 18.7, 'SELLO', oFont,,,, HPDF_TALIGN_CENTER )
         :CmSay( nOffset + 11.00, 18.7, 'DE', oFont,,,, HPDF_TALIGN_CENTER )
         :CmSay( nOffset + 11.5, 18.7, 'CAJA', oFont,,,, HPDF_TALIGN_CENTER )

         // Codigo
         :CmSay( nOffset + 12.7, 8.9, 'CAE: '+::CAE+' Vencimiento: '+DToC(StoD(::CAEVto)), oFontPrintR )
         :CmSay( nOffset + 13.5, 8.9, i2of5Encode( i2Of5(::cCUIT+::CbteTipo+::PtoVenta+::CAE+::CAEVto) ), oFont2of5 )

      END
   NEXT

   oPrint:CmDashLine( 14.85, 0.5, 14.85, 20.5 )
   oPrint:EndPage()

   oPrint:Save( cNombrePdf:= 'RC-'+::PtoVenta+'-'+StrZero(Val(::Numero),8)+'.pdf' )

RETURN cNombrePdf

 


Y el resultado de este código es

https://drive.google.com/file/d/0B3uWeE ... sp=sharing

El código seguramente resultará familiar para quien usa TPrinter.

Re: Felices reyes!

PostPosted: Fri Jan 06, 2017 1:37 pm
by armando.lagunas
Gracias!!

Probare tu aporte....


Saludos

Re: Felices reyes!

PostPosted: Fri Jan 06, 2017 2:22 pm
by cnavarro
Carlos, regalo recibido y bienvenido
Vaya "curro" que te has pegado, y la documentación "genial"
Muchas gracias, tiene muy buena pinta

Re: Felices reyes!

PostPosted: Fri Jan 06, 2017 3:27 pm
by joseluisysturiz
A caballo regalado no se le mira colmillo...y menos si es con buena intencion, descargando para probarla, como dice navarro se ve muy buena la pinta del sample, cualquier detalle o sugerencia seguro te llegara por este medio o a tu privado, gracias y saludos... :shock:

Re: Felices reyes!

PostPosted: Fri Jan 06, 2017 3:27 pm
by xmanuel
Carlos, sigues en Madrid?

Re: Felices reyes!

PostPosted: Fri Jan 06, 2017 6:00 pm
by Carlos Mora
xmanuel wrote:Carlos, sigues en Madrid?


Mientras no me echen... jaja.

Si Manu, ya estoy establecido, así es que a los que visiten Madrid será un placer poder invitaros con una cervecita. Y a los sevillanos que me recibisteis tan bien, devolveros las cortesías.

Un abrazo

Re: Felices reyes!

PostPosted: Fri Jan 06, 2017 6:47 pm
by Carlos Mora
HolA José Luis,

joseluisysturiz wrote:A caballo regalado no se le mira colmillo...y menos si es con buena intencion, descargando para probarla, como dice navarro se ve muy buena la pinta del sample, cualquier detalle o sugerencia seguro te llegara por este medio o a tu privado, gracias y saludos... :shock:

gracias por las pruebas, que es lo que hace falta para pulirla.

He subido un par de mejoras hace una hora, y un ejemplo completo y autocontenido:

https://drive.google.com/open?id=0B3uWe ... k9pZEdNR0k

El ejemplo es el prg de arriba, pero con constantes para que no requiera fuente de datos, y en modo consola, para que no haga falta la libreria gráfica.

Re: Felices reyes!

PostPosted: Fri Jan 06, 2017 7:34 pm
by xmanuel
El 15 estaré por ahí. El regalo que me ha hecho mi mujer, además de cachivaches para que adelgace, es poder deleitarme con el musical "La llamda" en el teatro Lara.
Llego el domingo y me voy el lunes, y creo que Isabel lo tiene todo orgnizado, pero si hay un hueco podemos vernos y charlar un rato.
Hazme llegar el numero de tu móvil por si las moscas. (A mi correo particular) :) :) :)

Re: Felices reyes!

PostPosted: Mon Jan 09, 2017 8:09 am
by hmpaquito
Estimado Carlos,

Felices Reyes Magos, con retraso... ;)

Grande, muy grande tu aporte.

En cuanto saque un hueco me pongo a probarlo.

Saludos

Re: Felices reyes!

PostPosted: Mon Jan 09, 2017 10:24 am
by AngelSalom
Buena pinta. Llevo usando HaruPdf hace un tiempo con muy buenos resultados. Veré tus ejemplos, gracias.

Re: Felices reyes!

PostPosted: Mon Jan 09, 2017 11:54 am
by karinha
Demopdf.exe, genera el archivo pdf, más no muestra el preview, esto está correcto? Gracias, saludos.

Re: Felices reyes!

PostPosted: Mon Jan 09, 2017 12:43 pm
by Carlos Mora
karinha wrote:Demopdf.exe, genera el archivo pdf, más no muestra el preview, esto está correcto? Gracias, saludos.


Si, correcto. La librería genera pdfs solamente, en realidad es la librería Haru, pero con cara de TPrinter. El ejemplo es en modo consola y está hecho a propósito para mostrar que no requiere librerías gráficas, para mostar lo simple del código para quien esté familiarizado con TPrinter, el ejemplo está bastante trabajado, y la calidad del pdf generado, muy compacto. Es un documento real usado en un programa de un cliente, e incluye impresión de codigo de barras e imágenes. Y el código lo tienes al 100%.
Las funciones de la librería resuelven tambien las cuestiones relativas a fuentes, que son las que más quebraderos de cabeza dan al hacer transformaciones, que al no hacer previews te lo evitas.

Re: Felices reyes!

PostPosted: Mon Jan 09, 2017 12:57 pm
by karinha
Gracias Carlos. Usando el sumatrapdf.exe para visualizar el myharu.pdf, creo que el código de barras, no esté generado correctamente:

Image

Saludos.

Re: Felices reyes!

PostPosted: Mon Jan 09, 2017 1:54 pm
by Carlos Mora
Ups!

Eso se debe a que la fuente ttf de los códigos de barra no está embebida. Ahora subo la corrección. Una forma de resolverlo es instalar en Windows la fuende i2of5txt.ttf que está incluída en el proyecto.

Hago las correcciones y la subo. Como dije en otro post, la gestión de las fuentes es todo un tema.

Gracias por las pruebas.