Este ejemplo del componente HotPDF convierte registros de la base de datos en una tabla PDF paginada. Es un patrón compacto de generación de informes: lee filas de un conjunto de datos, dibuja el encabezado de la tabla, imprime cada fila en una posición vertical conocida y agrega una nueva página cuando la página actual está llena.
El ejemplo utiliza una fuente de datos TTable heredada, pero la lógica de PDF es independiente de esa capa de almacenamiento. El mismo enfoque de renderizado se puede utilizar con FireDAC, ADO, conjuntos de datos en memoria, resultados REST o cualquier dato de aplicación que se pueda enumerar fila por fila.
El punto de diseño clave es separar el renderizado de filas de la configuración de la página. PrintRow dibuja una fila, PreparePage crea el encabezado repetido y los metadatos de la página, y el bucle principal controla la paginación. Esa separación hace que el ejemplo sea más fácil de adaptar a tablas más anchas, totales, agrupaciones o encabezados de informes con marca.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 |
program TableDemo; {$APPTYPE CONSOLE} { Reduce EXE size by disabling as much of RTTI as possible } {$IFDEF VER210} {$WEAKLINKRTTI ON} {$RTTI EXPLICIT METHODS([]) PROPERTIES([]) FIELDS([])} {$ENDIF} uses {$IFDEF VER230}System.Classes, System.SysUtils, Vcl.Graphics, DB, DBTables, {$ELSE} Classes, SysUtils, Graphics, DB, DBTables, {$ENDIF} HPDFDoc; var HotPDF: THotPDF; PageNum, VertPos: Integer; CustomerTable: TTable; Back: boolean; procedure PrintRow(Position: Integer; No, Company, Addr, City: AnsiString; ShowBackground: boolean); begin if ShowBackground then begin HotPDF.CurrentPage.SetRGBColor($FFF3DD); HotPDF.CurrentPage.Rectangle(50, Position, 520, 20); HotPDF.CurrentPage.Fill; HotPDF.CurrentPage.SetRGBColor(clBlack); end; HotPDF.CurrentPage.TextOut(70, Position, 0, No); HotPDF.CurrentPage.TextOut(110, Position, 0, Company); HotPDF.CurrentPage.TextOut(300, Position, 0, Addr); HotPDF.CurrentPage.TextOut(480, Position, 0, City); end; procedure PreparePage; begin HotPDF.CurrentPage.SetFont('Arial', [fsItalic], 10); HotPDF.CurrentPage.TextOut(50, VertPos, 0, 'customer.db' + ' Page' + AnsiString(IntToStr(PageNum))); HotPDF.CurrentPage.TextOut(480, VertPos, 0, AnsiString(DateTimeToStr(Now))); HotPDF.CurrentPage.MoveTo(50, VertPos + 15); HotPDF.CurrentPage.LineTo(570, VertPos + 15); HotPDF.CurrentPage.MoveTo(50, VertPos + 45); HotPDF.CurrentPage.LineTo(570, VertPos + 45); HotPDF.CurrentPage.Stroke; HotPDF.CurrentPage.SetFont('Times New Roman', [fsItalic, fsBold], 12); HotPDF.CurrentPage.SetRGBFillColor(clNavy); PrintRow(VertPos + 25, 'No', 'Company', 'Addr', 'City', false); HotPDF.CurrentPage.SetRGBFillColor(clBlack); Inc(VertPos, 20); end; begin CustomerTable := TTable.Create(nil); try CustomerTable.DatabaseName := 'DBDEMOS'; CustomerTable.TableName := GetCurrentDir + '\customer.db'; CustomerTable.Active := true; CustomerTable.First; HotPDF := THotPDF.Create(nil); try HotPDF.AutoLaunch := true; HotPDF.FileName := 'TableDemo.pdf'; HotPDF.PageLayout := plOneColumn; HotPDF.BeginDoc; HotPDF.CurrentPage.SetFont('Arial', [fsBold], 24); HotPDF.CurrentPage.TextOut(200, 20, 0, 'Customer report'); // Print PDF header PageNum := 1; VertPos := 60; PreparePage; // Table header Back := true; while (not(CustomerTable.Eof)) do begin Back := not(Back); if (VertPos > 700) then // If end of page then begin HotPDF.AddPage; // Add page, draw and print Inc(PageNum); // table header and set VertPos := 60; // new print position PreparePage; end; PrintRow(VertPos + 25, // print row from the current position AnsiString(CustomerTable.FieldValues['CustNo']), AnsiString(CustomerTable.FieldValues['Company']), AnsiString(CustomerTable.FieldValues['Addr1']), AnsiString(CustomerTable.FieldValues['City']), Back); Inc(VertPos, 20); CustomerTable.Next; end; HotPDF.EndDoc; finally HotPDF.Free; end; finally CustomerTable.Free; end; end. |
Qué adaptar en producción.
- Reemplace la tabla de muestra DBDEMOS con el conjunto de datos o el resultado de la consulta de la aplicación.
- Mida los anchos de las columnas a partir de los datos esperados en lugar de codificar cada coordenada x.
- Maneje el texto largo envolviéndolo o truncando los campos antes de dibujar la fila.
- Repita los encabezados de la tabla en cada nueva página para que los informes exportados sigan siendo legibles.
- Mantenga los márgenes de página y la altura de las filas en constantes con nombre para que los cambios de diseño sean predecibles.
¿Por qué es útil el dibujo directo de tablas PDF?
El dibujo directo proporciona un control total sobre las fuentes, los colores, los bordes, los saltos de página y las filas de resumen, sin depender de un diseñador de informes visual. Es especialmente útil para herramientas del lado del servidor o de tipo por lotes, donde el formato de salida debe permanecer estable en diferentes máquinas.