23 enero 2009

Creación de informes con QuickReport (IV)

Si creéis que con los informes que hemos hecho hemos cubierto casi todas las posibilidades estáis equivocados. La mente retorcida de nuestros clientes siempre hace dar otra vuelta de tuerca a nuestros informes hasta límites insospechados. Simplemente quieren verlo todo en un folio.

MAS DIFICIL TODAVIA

A partir de las tablas de CLIENTES y FACTURAS vamos a hacer un informe de ventas por cliente que nos va a mostrar lo que ha facturado cada uno (desglosado), con el total y un suma y sigue. Además vamos a totalizar toda la facturación:


Podéis verlo mejor si hacéis clic sobre la imagen. El diseño del informe sería este:


A la primera banda la vamos a llamar Cabecera y va a ser un objeto TQRBand cuya propiedad BandType será rbTitle. Sólo va a tener el título del listado y el encabezado:


La segunda banda se va a llamar Detalle y también será de tipo TQRBand. La banda va a ser de tipo rbDetail y va a mostrar los nombres de los clientes y las cabeceras de la factura mediante campos TQRDBText:


La tercera banda va a ser un objeto TQRSubDetail que vamos a llamar Subdetalle. En esta banda vamos a mostrar los importes de cada factura (también con TQRBText):


La cuarta banda también va a ser un objeto TQRSubDetalle que llamaremos Subdetalle2. Esta banda va a encargarse de totalizar las facturas de cada cliente y hacer un suma y sigue:


En esta banda, la primera fila de campos son etiquetas TQRLabel que vamos a reprogramar para que nos sumen el total de facturación de cada cliente. Para cumplir este cometido creamos en la sección privada del formulario de este informe estas variables:

private
{ Private declarations }
dSumaBase, dSumaIva, dSumaTotal: Double;

Ahora programamos el evento OnBeforePrint de la banda Detalle (rbDetail) para que inicialice estas variables y además nos filtre las facturas del cliente actual:

procedure TFListadoVentas.DetalleBeforePrint(Sender: TQRCustomBand;
var PrintBand: Boolean);
begin
with Form1 do
begin
Facturas.Filter := 'IDCLIENTE=' + #39 +
Clientes.FieldByName('ID').AsString + #39;
Facturas.Filtered := True;
end;

dSumaBase := 0;
dSumaIva := 0;
dSumaTotal := 0;
end;

Ahora le decimos antes de imprimir la banda Subdetalle2 que cambie las etiquetas por lo que llevamos aculumado:

procedure TFListadoVentas.Subdetalle2BeforePrint(Sender: TQRCustomBand;
var PrintBand: Boolean);
begin
ESUMABASE.Caption := FormatFloat( '###,###,#0.00', dSumaBase );
ESUMAIVA.Caption := FormatFloat( '###,###,#0.00', dSumaIva );
ESUMATOTAL.Caption := FormatFloat( '###,###,#0.00', dSumaTotal );
end;

Y para que haga la suma le decimos en el evento AfterPrint (después de imprimir) de la banda Detalle que vaya sumando los totales de cada registro:

procedure TFListadoVentas.SubdetalleAfterPrint(Sender: TQRCustomBand;
BandPrinted: Boolean);
begin
dSumaBase := dSumaBase + Form1.Facturas.FieldByName('BASEIMPONIBLE').AsFloat;
dSumaIva := dSumaIva + Form1.Facturas.FieldByName('IVA').AsFloat;
dSumaTotal := dSumaTotal + Form1.Facturas.FieldByName('TOTAL').AsFloat;
end;

Esta banda de totales también contiene campos de tipo TQRExpr (expresiones) que no van vinculados a bases de datos pero que permiten realizar operaciones con los campos del formulario. Estos campos los utilizamos para hacer el suma y sigue de todos los clientes. Para acumular la suma del campo BASEIMPONIBLE le decimos a la propiedad Expression del objeto TQRExpr que haga esto:


Igual tenemos que hacer para sumar el IVA y el TOTAL: SUM(IVA) y SUM(TOTAL), cada uno en su campo correspondiente. Como puede verse hay otras funciones para calcular la media, el máximo, pasar a mayúsculas, etc.

Y la quinta y última banda va a ser un objeto TQRBand cuyo tipo va a ser rbSummary. Aquí vamos a meter campos de tipo TQRExpr para sumar Base Imponible, Importe IVA y Total.

Aunque todo esto parezca una paranoia mental os puedo asegurar que se hace rápidamente respecto a otros editores como Rave (el que tenga valor que intente hacer este ejemplo).

Hay que procurar utilizar las funciones que trae el objeto TQRExpr para que nos resuelva los problemas, pero en casos como el que hemos visto de totales los podemos solucionar metiendo etiquetas y haciendo el trabajo a mano por programación.

EXPORTANDO EL INFORME A PDF

Aunque hoy en día se suelen utilizar programas como Primo PDF para convertir los documentos impresos a PDF, a los usuarios de los programas de gestión no les suele hacer mucha gracia porque cada vez que van a imprimir tiene que seleccionar la impresora Primo PDF y elegir la ubicación.

Por fortuna, las últimas versiones de QuickReport permiten exportar el formato a PDF. Esto podemos hacerlo directamente mediante código cuando vamos a imprimir el documento:

Application.CreateForm( TFListadoVentas, FListadoVentas );
FListadoVentas.Informe.ExportToFilter(
TQRPDFDocumentFilter.Create( 'C:\ListadoVentas.pdf' ) );

Para poder compilar esto tenemos que añadir la unidad QRPDFFilt en nuestro formulario. Con una sola línea de código hemos solucionado el problema.

EXPORTANDO A OTROS FORMATOS

Igualmente podemos pasarlo a HTML de este modo:

Application.CreateForm( TFListadoVentas, FListadoVentas );
FListadoVentas.Informe.ExportToFilter(
TQRGHTMLDocumentFilter.Create( 'C:\ListadoVentas.html' ) );

Este filtro necesita la unidad QRWebFilt.

Para exportar el informe a un documento RTF compatible con Microsoft Word sería así:

Application.CreateForm( TFListadoVentas, FListadoVentas );
FListadoVentas.Informe.ExportToFilter( TQRRTFExportFilter.Create( 'C:\ListadoVentas.rtf' ) );

Ese filtro necesita la unidad QRExport.

También podemos exportar a Microsoft Excel de este modo:

Application.CreateForm( TFListadoVentas, FListadoVentas );
FListadoVentas.Informe.ExportToFilter( TQRXLSFilter.Create( 'C:\ListadoVentas.xls' ) );

Utiliza también la unidad QRExport.

Si nos interesa extraer tanto los datos como los metadatos se puede exportar todo a XML:

Application.CreateForm( TFListadoVentas, FListadoVentas );
FListadoVentas.Informe.ExportToFilter( TQRXDocumentFilter.Create( 'C:\ListadoVentas.xml' ) );

Este filtro está en la unidad QRXMLSFilt.

Se puede exportar a un formato gráfico de 16 bits de gráficos vectoriales (aunque también soporta bitmaps) con extensión WMF que era antiguamente utilizado por Windows 3.0. Este formato puede verse con programas de diseño gráfico como GIMP. Se exporta de este modo:

var
FiltroWMF: TQRWMFExportFilter;
begin
FiltroWMF := TQRWMFExportFilter.Create( 'C:\ListadoVentas.wmf' );
Application.CreateForm( TFListadoVentas, FListadoVentas );
FListadoVentas.Informe.Prepare;
FListadoVentas.Informe.ExportToFilter( FiltroWMF );
end;

Un formato que considero muy interesante es pasarlo a texto plano para impresoras matriciales de tickets:

Application.CreateForm( TFListadoVentas, FListadoVentas );
FListadoVentas.Informe.ExportToFilter( TQRASCIIExportFilter.Create( 'C:\ListadoVentas.txt' ) );

Este formato de texto también viene muy bien para impresoras matriciales de papel continuo que tango nos castigan cuando se desajustan verticalmente.

Por último y no menos importante, tenemos el formato CSV que permite exportar los datos en texto plano entre comillas y separados por comas (ideal para exportar datos a Excel, Access, MySQL, etc.):

Application.CreateForm( TFListadoVentas, FListadoVentas );
FListadoVentas.Informe.ExportToFilter( TQRCommaSeparatedFilter.Create( 'C:\ListadoVentas.csv' ) );

Con esto cubrimos todas las necesidades de exportación de nuestros informes a otros programas ofimáticos y de terceros. Estos últimos filtros que hemos visto también tiran de la unidad QRExport.

No os podéis ni imaginar la cantidad de horas que he tenido que echar para averiguar como se exporta a todos estos formatos (mirando el código fuente). Todavía no entiendo por que narices los que fabrican componentes tan buenos como estos no les sale de los ... de escribir una documentación y ejemplos decentes (y eso también va por los Indy). No me extraña de que algunos programadores abandonen Delphi y elijan otros lenguajes por esta dificultad. No entiendo que a estas alturas (Delphi 2009) los programadores de Delphi tengamos que sufrir tanto para averiguar cuatro tonterías. A ver si "patera" technlogies se pone las pilas de una vez.

La semana que viene seguiré investigando para sacarle todo el partido posible a QuickRerport.

Pruebas realizadas en RAD Studio 2007.

Publicidad