La idea es: el .vrd pinta la factura; el PRG solo inyecta valores por ID de ítem.
Cómo está montada la factura
El invoice.vrd tiene 6 áreas:
┌──────┬─────────────────────┬──────────────────────────────────────────────────────┐
│ Área │ Archivo │ Qué es │
├──────┼─────────────────────┼──────────────────────────────────────────────────────┤
│ 1 │ invoice.v01 │ Cabecera: empresa, cliente, nº, fecha, vencimiento │
├──────┼─────────────────────┼──────────────────────────────────────────────────────┤
│ 2 │ invoice.v02 │ Títulos de columnas (código, descripción, cantidad…) │
├──────┼─────────────────────┼──────────────────────────────────────────────────────┤
│ 3 │ invoice.v03 │ Línea de detalle (fila clara) │
├──────┼─────────────────────┼──────────────────────────────────────────────────────┤
│ 6 │ invoiceSchatten.v03 │ Línea de detalle (fila sombreada, cebra) │
├──────┼─────────────────────┼──────────────────────────────────────────────────────┤
│ 4 │ invoice.v04 │ Totales: base, IVA, total │
├──────┼─────────────────────┼──────────────────────────────────────────────────────┤
│ 5 │ Ganze Seite │ Fondo de página (se imprime primero) │
└──────┴─────────────────────┴──────────────────────────────────────────────────────┘
Cada texto del diseñador tiene un ID. Ese ID es el que usas en ITEMIDS.
Código mínimo para imprimirla
#include "FiveWin.ch"
#include "easyrep.ch"
FUNCTION PrintInvoice( lPreview, oWnd )
LOCAL oVRD, n, nPrintArea := 3
LOCAL nTotal := 0, nVAT := 0
LOCAL aLines
// Cabecera de la factura (puedes venir de un DBF)
LOCAL cCompany := "EasyReport Comp."
LOCAL cAddress := "Calle Mayor 12" + CRLF + "28013 Madrid"
LOCAL cCIF := "B-12345678"
LOCAL cInvNum := "2026-0042"
LOCAL dDate := Date()
LOCAL dPayDate := Date() + 30
LOCAL nTaxRate := 21
// Líneas: código, descripción, cantidad, precio, dto
aLines := { ;
{ "A001", "Monitor 27 pulgadas", 2, 189.00, 0 }, ;
{ "A002", "Teclado mecanico", 1, 79.50, 5 }, ;
{ "A003", "Cable HDMI 2m", 3, 12.00, 0 } }
EASYREPORT oVRD NAME "yinvoice\invoice.vrd" ;
PREVIEW lPreview OF oWnd MODAL
IF oVRD:lDialogCancel
RETURN .F.
ENDIF
// 5 = fondo de página
PRINTAREA 5 OF oVRD
// 1 = cabecera (IDs del invoice.v01)
PRINTAREA 1 OF oVRD ;
ITEMIDS { 201, 500, 501, 602, 502, 603 } ;
ITEMVALUES { cCompany, cAddress, cCIF, cInvNum, ;
DToC( dDate ), DToC( dPayDate ) }
// 2 = títulos de columnas
PRINTAREA 2 OF oVRD
// 3 / 6 = líneas (cebra)
FOR n := 1 TO Len( aLines )
nTotal += aLines[ n, 3 ] * aLines[ n, 4 ] - aLines[ n, 5 ]
Code: Select all | Expand
PRINTAREA nPrintArea OF oVRD ;
ITEMIDS { 200, 201, 202, 203, 204, 205 } ;
ITEMVALUES { aLines[ n, 1 ], ;
aLines[ n, 2 ], ;
AllTrim( Str( aLines[ n, 3 ] ) ), ;
AllTrim( Str( aLines[ n, 4 ], 10, 2 ) ), ;
AllTrim( Str( aLines[ n, 5 ] ) ), ;
AllTrim( Str( aLines[ n, 3 ] * aLines[ n, 4 ] - aLines[ n, 5 ], 12, 2 ) ) }
nPrintArea := If( nPrintArea == 3, 6, 3 ) // fila clara / sombreada
NEXT
nVAT := nTotal * nTaxRate / 100
// 4 = pie de totales
PRINTAREA 4 OF oVRD ;
ITEMIDS { 310, 311, 312, 313 } ;
ITEMVALUES { AllTrim( Str( nTotal, 12, 2 ) ), ;
AllTrim( Str( nTaxRate, 5, 2 ) ), ;
AllTrim( Str( nVAT, 12, 2 ) ), ;
AllTrim( Str( nTotal + nVAT, 12, 2 ) ) }
END EASYREPORT oVRD
RETURN .T.
Los IDs tienen que coincidir con los del diseñador. En invoice.v01 / invoice.v03 / invoice.v04 están así:
┌─────────┬─────────────────────────────────────────────────────┐
│ ID │ Campo │
├─────────┼─────────────────────────────────────────────────────┤
│ 201 │ Empresa │
├─────────┼─────────────────────────────────────────────────────┤
│ 500 │ Dirección cliente │
├─────────┼─────────────────────────────────────────────────────┤
│ 501 │ CIF │
├─────────┼─────────────────────────────────────────────────────┤
│ 602 │ Nº factura │
├─────────┼─────────────────────────────────────────────────────┤
│ 502 │ Fecha │
├─────────┼─────────────────────────────────────────────────────┤
│ 603 │ Vencimiento │
├─────────┼─────────────────────────────────────────────────────┤
│ 200–205 │ Código, descripción, cantidad, precio, dto, importe │
├─────────┼─────────────────────────────────────────────────────┤
│ 310–313 │ Base, % IVA, cuota IVA, total │
└─────────┴─────────────────────────────────────────────────────┘
Si el texto no sale, casi siempre es que el ID del PRG no es el del .v01.
Cómo verlo y editarlo
- Diseñador:
cd C:\fwteam\samples\EasyReport
C:\fwteam\samples\build_new.bat erdsample hb32
Abre ..\yinvoice\invoice.vrd y mira cada área. En cada texto, el ID es el número que luego pasas en ITEMIDS.
- App de facturación completa (clientes, líneas, preview):
cd C:\fwteam\samples\misc
C:\fwteam\samples\build_new.bat yunus hb32
En Invoices hay un botón que llama a ViewInvoiceER().
Flujo típico de una factura
PRINTAREA 5 // fondo / membrete de página
PRINTAREA 1 // cabecera (datos fijos de esta factura)
PRINTAREA 2 // títulos de columnas
loop líneas:
PRINTAREA 3 o 6 // cada fila
si se acaba la página: PAGEBREAK + cabecera otra vez
PRINTAREA 4 // totales (reserva sitio: oVRD:nPageBreak - oVRD:aAreaHeight[4])
END EASYREPORT
Si hay muchas líneas, mira samples\EasyReport\examples\SourceExample2.prg: comprueba oVRD:nNextRow > oVRD:nPageBreak y hace PAGEBREAK oVRD antes de que los totales se corten.
PDF directo (sin diálogo):
EASYREPORT oVRD NAME "yinvoice\invoice.vrd" PREVIEW .T. FILE "factura.pdf"
Otra vía: expresiones (Cargo)
En SourceExample1.prg (albarán/pedido) no se pasan todos los IDs. El diseñador usa expresiones tipo oVRD:Cargo[1] y el PRG solo rellena el array:
oVRD:Cargo := { "Nr. 12345 Date: 5.9.2004", ; // 1
"Testclient", ; // 2
... }
PRINTAREA 5 OF oVRD // el .vrd ya sabe qué Cargo[n] pintar
Para una factura, ITEMIDS/ITEMVALUES (como yunus) suele ser más claro.