Dieses HotPDF-Komponentenbeispiel konvertiert Datenbankeinträge in eine paginierte PDF-Tabelle. Es ist ein kompaktes Berichtserstellungsmuster: Lesen Sie Zeilen aus einem Datensatz, zeichnen Sie die Tabellenüberschrift, drucken Sie jede Zeile an einer bekannten vertikalen Position und fügen Sie eine neue Seite hinzu, wenn die aktuelle Seite voll ist.
Das Beispiel verwendet eine veraltete TTable-Datenquelle, aber die PDF-Logik ist unabhängig von dieser Datenspeicherschicht. Der gleiche Rendering-Ansatz kann mit FireDAC, ADO, In-Memory-Datensätzen, REST-Ergebnissen oder jedem Anwendungsdatensatz verwendet werden, der zeilenweise durchlaufen werden kann.
Der wichtigste Designaspekt ist die Trennung des Zeilen-Renderings von der Seitenaufbereitung. PrintRow zeichnet eine Zeile, PreparePage erstellt die wiederholte Überschrift und die Seitenmetadaten, und die Hauptschleife steuert die Paginierung. Diese Trennung macht das Beispiel einfacher anpassbar für breitere Tabellen, Gesamtsummen, Gruppierungen oder markenspezifische Berichtüberschriften.
|
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. |
Was im Produktionsbetrieb angepasst werden muss
- Ersetzen Sie die Beispiel-DBDEMOS-Tabelle durch den Anwendungsdatensatz oder das Abfrageergebnis.
- Messen Sie die Spaltenbreiten anhand der erwarteten Daten anstelle der harten Kodierung jeder x-Koordinate.
- Behandeln Sie langen Text, indem Sie Felder umbrechen oder abschneiden, bevor die Zeile gezeichnet wird.
- Wiederholen Sie die Tabellenüberschriften auf jeder neuen Seite, damit exportierte Berichte lesbar bleiben.
- Behalten Sie Seitenränder und Zeilenhöhe in benannten Konstanten, um Layoutänderungen vorhersehbar zu machen.
Warum das direkte Zeichnen von PDF-Tabellen nützlich ist.
Das direkte Zeichnen bietet volle Kontrolle über Schriftarten, Farben, Rahmen, Seitenumbrüche und Zusammenfassungszeilen, ohne auf einen visuellen Berichtsentwickler angewiesen zu sein. Es ist besonders nützlich für serverseitige oder Batch-Tools, bei denen das Ausgabeformat über verschiedene Maschinen hinweg stabil bleiben muss.