html HotPDF Tabela do PDF | losLab Software Development Blog

Artykuł techniczny

HotPDF Tabela do PDF

· Oprogramowanie PDF

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]