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