مقالة تقنية

نموذج مخطط HotPDF

هذا المثال لمكون HotPDF يقوم بتصدير رسم بياني Delphi TeeChart إلى مستند PDF. يوضح المثال حلقة وصل عملية بين الرسوم البيانية التفاعلية VCL وتقارير PDF القابلة للتوزيع: يمكن للمستخدمين تكوين نمط الرسم البياني في النموذج، ثم يقوم التطبيق بطباعة حالة الرسم البياني المحددة في صفحة PDF.

الكود مفيد للوحة المعلومات، وتقارير الهندسة، وملخصات مالية، وأي تطبيق Delphi يستخدم بالفعل TeeChart للعرض المرئي على الشاشة. بدلاً من إعادة بناء الرسم البياني يدويًا باستخدام استدعاءات رسم PDF، يسمح المثال لـ TeeChart بعرض نفسه على مساحة الرسم الخاصة بـ HotPDF.

متى يفيد هذا النمط

غالباً ما يكون تصدير المخطط مطلوباً بعد أن يكون المخطط قد ضُبط تفاعلياً. قد يكون المستخدم اختار وضع التكديس أو غيّر السلاسل المرئية أو رشّح البيانات أو بدّل بين العرض بالقيم المطلقة والنسبية. التقاط حالة TeeChart الحالية يجعل ملف PDF مطابقاً لما راجعه المستخدم على الشاشة.

يحافظ هذا النهج أيضاً على صغر كود التقرير. يبقى TeeChart مسؤولاً عن المحاور والتسميات ووسائل الإيضاح وأنماط الأعمدة والسلاسل، بينما يدير HotPDF دورة حياة مستند PDF وcanvas الصفحة. هذا الفصل أسهل في الصيانة من تكرار كل قاعدة من قواعد المخطط داخل روتين رسم PDF مستقل.

قبل التصدير

  • اضبط المخطط على الحالة المرئية التي يجب أن تظهر في PDF.
  • اختر مستطيل مخطط يناسب اتجاه الصفحة وهوامشها.
  • احجز مساحة لعنوان التقرير والمرشحات ونطاق التاريخ وملاحظات مصدر البيانات إذا كان 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
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],clTeeColor);
  with BarSeries2 do
   for H:=1 to 12 do Add( Random(100),FormatSettings.ShortMonthNames[H],clTeeColor);
  with BarSeries3 do
  for H:=1 to 12 do Add( Random(100),FormatSettings.ShortMonthNames[H],clTeeColor);
  {$ELSE}
  with BarSeries1 do
   for H:=1 to 12 do Add( Random(100),ShortMonthNames[H],clTeeColor);
  with BarSeries2 do
   for H:=1 to 12 do Add( Random(100),ShortMonthNames[H],clTeeColor);
  with BarSeries3 do
  for H:=1 to 12 do Add( Random(100),ShortMonthNames[H],clTeeColor);
  {$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.

مسار التصدير.

  • يقوم النموذج بإنشاء بيانات رسم بياني عينة ويسمح للمستخدم باختيار تخطيط الشريط.
  • يقوم زر التصدير بإنشاء كائن THotPDF ويختار اسم ملف الإخراج بناءً على وضع الرسم البياني.
  • ChartRect يحدد منطقة الرسم المستهدفة على صفحة PDF.
  • DemoChart.PrintPartialCanvas يقوم بعرض الرسم البياني على مساحة الرسم الخاصة بـ PDF.
  • EndDoc ينهي ملف PDF.

توصيات بشأن التخطيط.

حافظ على تناسق شكل المستطيل في الرسم البياني مع مساحة الرسم البياني الظاهرة على الشاشة، واختبر تسميات المحاور مع النصوص الطويلة المترجمة. إذا كان ملف PDF جزءًا من تقرير، فاحتفظ بمساحة للعنوان والطابع الزمني ومصدر البيانات والملاحظات بحيث يظل الرسم البياني مفهومًا عند عرضه خارج التطبيق الأصلي.

قائمة فحص الإنتاج

  • ضع إنشاء THotPDF داخل try/finally حتى تُحرر المكوّنة بعد فشل التصدير.
  • استخدم بيانات مخطط ثابتة لاختبارات الانحدار بدلاً من Randomize.
  • حدد ما إذا كان كل وضع مخطط سيستبدل اسم ملف ثابتاً أو سيطلب وجهة.
  • تحقق من النتيجة ببيانات تحتوي على سلاسل فارغة وقيم سالبة وتسميات فئات طويلة.

في التقارير متعددة المخططات، امنح كل مخطط مقطع صفحة خاصاً وحافظ على اتساق خيارات المقياس بين الصفحات. يقارن القراء صفحات PDF جنباً إلى جنب، لذلك قد يجعل تغيير نطاق المحور أو ترتيب وسيلة الإيضاح تصديراً صحيحاً يبدو مضللاً.

مشكلات شائعة

الخطأ الأكثر شيوعاً هو التعامل مع التقاط المخطط كلقطة شاشة bitmap. يستخدم هذا المثال مسار canvas الخاص بالمخطط، مما يحافظ على إخراج أنظف ويتجنب الاعتماد على دقة الشاشة. المشكلة الشائعة الأخرى هي القص: يجب اختبار المستطيل المرسل إلى PrintPartialCanvas مع أكبر وسيلة إيضاح وتسميات متوقعة.