Ten przykładowy komponent HotPDF konwertuje rekordy bazy danych na tabelę PDF podzieloną na strony. Jest to kompaktowy wzorzec generowania raportów: czytaj wiersze ze zbioru danych, rysuj nagłówek tabeli, drukuj każdy wiersz w znanej pozycji pionowej i dodawaj nową stronę, gdy bieżąca strona jest pełna.
W przykładzie wykorzystano starsze źródło danych TTable, ale logika PDF jest niezależna od tej warstwy przechowywania. To samo podejście do renderowania można zastosować w przypadku FireDAC, ADO, zestawów danych w pamięci, wyników REST lub dowolnych danych aplikacji, które można wyliczać wiersz po wierszu.
Kluczowym założeniem projektowym jest oddzielenie renderowania wierszy od konfiguracji strony. PrintRow rysuje jeden wiersz, PrzygotowaniePage tworzy powtarzające się metadane nagłówka i strony, a główna pętla kontroluje paginację. Taka separacja ułatwia dostosowanie próbki do szerszych tabel, sum, grupowania lub nagłówków raportów opatrzonych marką.
Zakreślacz składni Urvanov v2.9.1|
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. |
Co dostosować w produkcji
- Zastąp przykładową tabelę DBDEMOS zbiorem danych aplikacji lub wynikiem zapytania.
- Zmierz szerokość kolumn na podstawie oczekiwanych danych, zamiast kodować na stałe każdą współrzędną x.
- Obsługa długiego tekstu poprzez zawijanie lub obcinanie pól przed narysowaniem wiersza.
- Powtarzaj nagłówki tabeli na każdej nowej stronie, aby wyeksportowane raporty pozostały czytelne.
- Zachowaj marginesy strony i wysokość wierszy w nazwanych stałych, aby zmiany układu były przewidywalne.
Dlaczego bezpośrednie rysowanie tabeli PDF jest przydatne
Bezpośrednie rysowanie daje pełną kontrolę nad czcionkami, kolorami, obramowaniami, podziałami stron i wierszami podsumowań, bez konieczności polegania na projektantze raportów wizualnych. Jest to szczególnie przydatne w przypadku narzędzi po stronie serwera lub narzędzi wsadowych, gdzie format wyjściowy musi pozostać stabilny na wszystkich komputerach.
[Czas formatowania: 0,0033 sekundy]