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.1Struktura raportu
Eksporter tabel PDF potrzebuje więcej niż pętli po rekordach. Wynik musi zachować wyrównanie kolumn, powtarzać kontekst na każdej stronie i sprawiać, że ostatnia strona wygląda celowo nawet przy kilku wierszach. Przykład pokazuje minimalną strukturę: procedurę przygotowania strony, procedurę rysowania wiersza i główną pętlę kontrolującą podziały stron.
Taka struktura daje kodowi produkcyjnemu jasne miejsca rozszerzeń. Procedura nagłówka może dodać logo, nazwę raportu, podsumowanie filtrów i numery stron. Procedura wiersza obsłuży wyrównanie, zawijanie, naprzemienne tła albo formatowanie liczb. Pętla może dodać grupy, sumy i znaczniki kontynuacji bez przepisywania rysowania.
Kontrole granic danych
- Ustal, jak renderować pola null przed narysowaniem wiersza.
- Zmierz tekst, który może przekroczyć szerokość kolumny, i wybierz zawijanie, obcięcie albo wielokropek.
- Wartości liczbowe wyrównuj do prawej, gdy raport służy do porównań.
- Puste datasety obsługuj czytelną stroną zastępczą zamiast pustego PDF.
|
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]Kosztem jest jawność decyzji układu. Zwykle dobrze pasuje to do raportów operacyjnych, faktur, eksportów audytowych i narzędzi batch, gdzie wynik ma być stabilny, a programista chce przewidywalnie kontrolować każdy drukowany element.
Lista walidacyjna
- Wygeneruj raport z zerem wierszy, jednym wierszem, dokładnie jedną pełną stroną i jednym wierszem za granicą strony.
- Przetestuj najszersze oczekiwane wartości w każdej kolumnie.
- Otwórz wygenerowany PDF w więcej niż jednej przeglądarce, aby wychwycić różnice fontów lub przycięcia.
- Sprawdź, czy powtarzane nagłówki, marginesy i numery stron pozostają spójne po lokalizacji.