Cet exemple de composant HotPDF convertit les enregistrements de la base de données en un tableau PDF paginé. Il s'agit d'un modèle compact de génération de rapports : lire les lignes d'un ensemble de données, dessiner l'en-tête du tableau, imprimer chaque ligne à une position verticale connue et ajouter une nouvelle page lorsque la page actuelle est pleine.
L'exemple utilise une source de données TTable héritée, mais la logique PDF est indépendante de cette couche de stockage. La même approche de rendu peut être utilisée avec FireDAC, ADO, des ensembles de données en mémoire, des résultats REST ou toute application de données qui peut être énumérée ligne par ligne.
Le point de conception clé est de séparer le rendu des lignes de la configuration de la page. PrintRow dessine une ligne, PreparePage crée l'en-tête répété et les métadonnées de la page, et la boucle principale contrôle la pagination. Cette séparation rend l'exemple plus facile à adapter à des tableaux plus larges, des totaux, des regroupements ou des en-têtes de rapports personnalisés.
|
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. |
Ce qu'il faut adapter en production.
- Remplacez le tableau DBDEMOS de l'exemple par l'ensemble de données ou le résultat de la requête de l'application.
- Déterminez les largeurs des colonnes à partir des données attendues au lieu de coder en dur chaque coordonnée x.
- Gérez les longs textes en les retournant à la ligne ou en tronquant les champs avant de dessiner la ligne.
- Répétez les en-têtes de tableau sur chaque nouvelle page pour que les rapports exportés restent lisibles.
- Conservez les marges de page et la hauteur des lignes dans des constantes nommées pour rendre les modifications de mise en page plus prévisibles.
Pourquoi le dessin direct des tableaux PDF est utile.
Le dessin direct offre un contrôle total sur les polices, les couleurs, les bordures, les sauts de page et les lignes de résumé, sans dépendre d'un concepteur de rapports visuel. Il est particulièrement utile pour les outils côté serveur ou de type batch où le format de sortie doit rester stable sur différentes machines.