Technical Article

HotPDF Chart Sample

This HotPDF Component example exports a Delphi TeeChart chart into a PDF document. The sample demonstrates a practical bridge between interactive VCL charting and distributable PDF reports: users can configure the chart style in the form, then the application prints the selected chart state to a PDF page.

  • Map this hotpdf chart workflow to UK deployment expectations before release
  • Review governance controls for audit trails, retention, and sign-off windows
  • Run accessibility and rendering checks in your standard UK QA toolchain
  • Capture approved fixtures in version control and use them as regression baselines

UK delivery readiness checklist

The code is useful for dashboards, engineering reports, financial summaries, and any Delphi application that already uses TeeChart for on-screen visualization. Instead of rebuilding the chart manually with PDF drawing calls, the example lets TeeChart render itself onto the HotPDF page canvas.

When this pattern helps

Chart export is often needed after the chart has already been configured interactively. The user may have selected a stacking mode, changed the visible series, filtered the data, or switched between absolute and percentage views. Capturing that current TeeChart state keeps the exported PDF aligned with what the user reviewed on screen.

The same approach also keeps the reporting code small. TeeChart remains responsible for axes, labels, legends, bar styles, and series rendering, while HotPDF handles the PDF document lifecycle and page canvas. That division is easier to maintain than duplicating every chart rule in a separate PDF drawing routine.

Before exporting

  • Set the chart to the visual state that should appear in the PDF.
  • Choose a chart rectangle that matches the target page orientation and margins.
  • Reserve space for report title, filters, date range, and data source notes if the PDF will be archived.
  • Test long labels and localised month names before shipping the export feature.
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
96
97
98
99
100
101
102
103
104
105
106
107
unit ChartUnit;
 
interface
 
uses
  {$IF CompilerVersion >= 16} Winapi.Windows, Winapi.Messages, System.SysUtils, System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Vcl.ExtCtrls, VclTee.TeeGDIPlus, VclTee.TeEngine, VclTee.Series, VclTee.TeeProcs, VclTee.Chart,
  {$ELSE}Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, ExtCtrls, TeEngine, Series, TeeProcs, Chart,
  {$ENDIF} HPDFDoc;
 
type
  TForm1 = class(TForm)
    RadioGroup1: TRadioGroup;
    DemoChart: TChart;
    BarSeries1: TBarSeries;
    BarSeries2: TBarSeries;
    BarSeries3: TBarSeries;
    Panel1: TPanel;
    Label1: TLabel;
    RadioGroup2: TRadioGroup;
    ComboBox1: TComboBox;
    Button1: TButton;
    procedure RadioGroup1Click(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure RadioGroup2Click(Sender: TObject);
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;
 
var
  Form1: TForm1;
 
implementation
 
{$R *.DFM}
 
procedure TForm1.RadioGroup1Click(Sender: TObject);
begin
  Case RadioGroup1.ItemIndex of
    0: BarSeries1.MultiBar:=mbNone;
    1: BarSeries1.MultiBar:=mbSide;
    2: BarSeries1.MultiBar:=mbStacked;
    3: BarSeries1.MultiBar:=mbStacked100;
  end;
end;
 
procedure TForm1.FormCreate(Sender: TObject);
var
  H: Integer;
begin
  DemoChart.View3D:=False;
  Randomize;
  {$IFDEF VER220}
  with BarSeries1 do
   for H:=1 to 12 do Add( Random(100),FormatSettings.ShortMonthNames[H],clTeeColour);
  with BarSeries2 do
   for H:=1 to 12 do Add( Random(100),FormatSettings.ShortMonthNames[H],clTeeColour);
  with BarSeries3 do
  for H:=1 to 12 do Add( Random(100),FormatSettings.ShortMonthNames[H],clTeeColour);
  {$ELSE}
  with BarSeries1 do
   for H:=1 to 12 do Add( Random(100),ShortMonthNames[H],clTeeColour);
  with BarSeries2 do
   for H:=1 to 12 do Add( Random(100),ShortMonthNames[H],clTeeColour);
  with BarSeries3 do
  for H:=1 to 12 do Add( Random(100),ShortMonthNames[H],clTeeColour);
  {$ENDIF}
  ComboBox1.Items.Clear;
  for H:=0 to DemoChart.SeriesCount-1 do
    ComboBox1.Items.Add(DemoChart.Series[H].Name);
  ComboBox1.ItemIndex:=0;
end;
 
procedure TForm1.RadioGroup2Click(Sender: TObject);
begin
  With DemoChart.Series[ComboBox1.ItemIndex] as TBarSeries do
    BarStyle:=TBarStyle(RadioGroup2.Itemindex);
end;
 
procedure TForm1.Button1Click(Sender: TObject);
var
  HotPDF: THotPDF;
  ChartRect: TRect;
begin
  HotPDF := THotPDF.Create(nil);
  try
    case RadioGroup1.ItemIndex of
      0: HotPDF.FileName := 'PDFChart-Behind.pdf';
      1: HotPDF.FileName := 'PDFChart-SideToSide.pdf';
      2: HotPDF.FileName := 'PDFChart-Stacked.pdf';
      3: HotPDF.FileName := 'PDFChart-Stacked100.pdf';
    end;
    HotPDF.BeginDoc;
    ChartRect.Left := 0;
    ChartRect.Right := 800;
    ChartRect.Top := 0;
    ChartRect.Bottom := 600;
    DemoChart.PrintPartialCanvas( HotPDF.CurrentPage.Canvas, ChartRect );
    HotPDF.EndDoc;
  finally
    HotPDF.Free;
  end;
end;
 
end.

Export flow

  • The form creates sample chart data and lets the user choose the bar layout.
  • The export button creates THotPDF and selects an output file name based on the chart mode.
  • ChartRect defines the target drawing area on the PDF page.
  • DemoChart.PrintPartialCanvas renders the chart into the PDF canvas.
  • EndDoc finalizes the PDF file.

Layout recommendations

Keep the chart rectangle proportional to the on-screen chart area, and test axis labels with long localized text. If the PDF is part of a report, reserve space for a title, timestamp, data source, and notes so the chart remains meaningful when viewed outside the original application.

Production checklist

  • Wrap THotPDF creation in try/finally so the component is released after failed exports.
  • Use deterministic chart data for regression tests instead of Randomize.
  • Decide whether each chart mode should overwrite a fixed file name or prompt for a destination.
  • Validate the result with sample data that includes empty series, negative values, and long category labels.

For multi-chart reports, give each chart its own page section and keep scale choices consistent across pages. Readers compare PDF pages side by side, so changing the axis range or legend order between charts can make a correct export look misleading.

Common pitfalls

The most common mistake is treating the chart capture as a bitmap screenshot. This sample uses the chart canvas path instead, which preserves cleaner output and avoids screen-resolution dependencies. Another common issue is clipping: the rectangle passed to PrintPartialCanvas should be tested with the largest expected legend and label set.