기술 문서

HotPDF 테이블을 PDF로

· PDF 소프트웨어

이 HotPDF 컴포넌트 샘플은 데이터베이스 레코드를 페이지가 있는 PDF 테이블로 변환합니다. 이는 간결한 보고서 생성 패턴으로, 데이터 세트에서 행을 읽고, 테이블 헤더를 그리고, 각 행을 알려진 수직 위치에 출력하며, 현재 페이지가 가득 차면 새 페이지를 추가합니다.

이 예제에서는 레거시 TTable 데이터 소스를 사용하지만, PDF 로직은 해당 저장 계층에 독립적입니다. 동일한 렌더링 방식을 FireDAC, ADO, 메모리 데이터 세트, REST 결과 또는 행 단위로 나열할 수 있는 모든 애플리케이션 데이터와 함께 사용할 수 있습니다.

핵심 설계 포인트는 행 렌더링과 페이지 설정을 분리하는 것입니다. PrintRow는 한 행을 그립니다, PreparePage는 반복되는 헤더와 페이지 메타데이터를 생성하고, 메인 루프는 페이지 나누기를 제어합니다. 이러한 분리는 샘플을 더 넓은 테이블, 총계, 그룹화 또는 브랜드 보고서 헤더에 더 쉽게 적용할 수 있도록 합니다.

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.

프로덕션 환경에서 적용해야 할 사항

  • 샘플 DBDEMOS 테이블을 애플리케이션 데이터 세트 또는 쿼리 결과로 대체합니다.
  • 모든 x 좌표를 하드 코딩하는 대신, 예상 데이터에서 열 너비를 측정합니다.
  • 행을 그리기 전에 긴 텍스트를 줄 바꿈하거나 잘라서 처리합니다.
  • 내보낸 보고서의 가독성을 유지하기 위해 각 새 페이지에 테이블 헤더를 반복합니다.
  • 페이지 여백과 행 높이를 명명된 상수 값으로 유지하여 레이아웃 변경을 예측 가능하게 합니다.

PDF 테이블을 직접 그리는 것이 유용한 이유

직접 그리기는 글꼴, 색상, 테두리, 페이지 나누기 및 요약 행에 대한 완전한 제어를 제공하며, 시각적 보고서 설계 도구에 의존하지 않습니다. 이는 특히 서버 측 또는 일괄 처리 도구에서 출력 형식이 여러 시스템에서 일관성을 유지해야 하는 경우에 유용합니다.