QuickReport から sgcReports への移行

sgcReports は sgcUI のバンド型レポートエンジンです。TsgcReport がレイアウトを保持し、TsgcReportEngine がデータをバインドし、TsgcReportPreviewVCL がページを表示し、PDF エクスポートはタグ付き PDF/UA を出力します。このキットでは、お使いの QuickReport のバンドとコントロールを sgcReports の対応メンバーに結び付け、コンパイル済みデモのコードを示し、対応しない点も率直に挙げます。

QuickReport で作られた Delphi VCL のレポート

フォーム上の TQuickRep、バンド、バンド上の QR コントロール、そしてアプリケーション内のプレビュー、印刷、PDF ボタンです。

QuickReport は再びメンテナンスされています。"QuickReport is back" (Embarcadero ブログ、Ian Barker、2024 年 11 月 14 日) で Embarcadero は、主任開発者が亡くなって製品が危機に陥ったこと、Embarcadero のパートナーである Barnsten とともに復活させたこと、そして現在は Delphi 7 以降の Delphi と C++Builder を含む RAD Studio のすべてのバージョンに対応していることを説明しています。Barnsten の QuickReport のページ (2026-10-20 に確認) には、TrueType フォントを埋め込める PDF フィルター、PDF/A のサポート、HTML、XML/XSLT、XLS、XLSX のエクスポートフィルターが記載され、QuickReport Pro 5 開発者版の価格は税別 EUR 2.155,00 です。したがって、このページは終わった製品や欠けている PDF ボタンの話ではありません。その機能一覧に載っていないものを求めるチーム向けです。

sgcReports が加えるもの

以下の sgcReports に関する記述はすべて、製品のソースコードで確認できます。QuickReport 側は、ベンダーのページに記載がない箇所を「サポートされない」ではなく「記載なし」としています。

アクセシブルな PDF/UA

TsgcReportPDFExport は既定でタグ付き PDF/UA を出力します (PDFUA は True、PDFUAPart でパート 1 か 2 を選択)。読み上げ順序、項目の TagRole による見出しの役割、AltText による代替テキスト、文書の Language と Title を含みます。PDFA を指定すると、アーカイブ向けに PDF/A-3b、PDF/A-3a、PDF/A-4 を出力できます。Community を含むすべてのエディションで利用できます。PDF/UA とタグ付き PDF は Barnsten の機能ページには記載がありません。電子書籍、電子商取引、銀行サービスなどの製品とサービスを対象とする 欧州アクセシビリティ法 (Directive (EU) 2019/882) 以降、アクセシブルな文書の重要性は高まっています。

エンドユーザー向けデザイナー (VCL と FireMonkey)

ユーザーは新しいビルドなしでレポートを変更できます。sgcShowReportDesigner(Engine) で VCL デザイナーが開き、TsgcVCLReportDesigner パネルを埋め込むこともできます。sgcShowReportDesignerFMX(Engine) は FireMonkey で同じことを行います (Delphi XE6 以降、デスクトップ)。VCL デザイナーはフォームの DPI 変更に追従します (インスペクター、アイコン、デザインサーフェスが ChangeScale で拡大縮小されます)。Registered エディションのみです。Barnsten の機能ページにエンドユーザー向けデザイナーの記載はなく、従来はサードパーティ製の別製品 QRDesign でした。High DPI については、2022 年 4 月 4 日の Delphi-PRAXiS の返信で、QuickReport 6 は Delphi 11.1 でビルドできるものの High-DPI には対応していないと述べられていました。最新のリリースはベンダーにご確認ください。

スイート全体で共通の 1 つのエンジン

クロス集計、バーコード、サブレポート、リッチテキストは、同じバンドエンジンの項目の種類です。ブリッジユニットを使うと、レポートは sgcCharts のチャートと sgcPivotGrid のピボットテーブルも項目として印刷し、PDF ではベクターとして描画します (Registered エディション)。エクスポートは、PDF、XLSX、CSV、HTML、PNG がすべてのエディションで、DOCX は Registered エディションで利用できます。

JSON 定義と .NET 版

レポートは JSON で保存および読み込みができるため (TsgcReport.SaveToFile、LoadFromFile)、レイアウトをデータベースやバージョン管理に置けます。同じ定義を .NET 版の sgcReports (NuGet の esegece.sgcReports、.NET Standard 2.0、.NET Framework 4.7.2、.NET 6 以降) で読み込めるため、Delphi のレポートを .NET サービスで再利用できます。

レポートはインポートではなく作り直します。sgcReports は QuickReport の .dfm を開けません。QuickReport のインポーターはありません。各レポートは、以下のデモのようにコードで、または sgcReports のデザイナー (Registered エディション) で作り直します。このページのマッピングと手順に従えば、バンドごとの機械的な作業になります。sgcReports は開発者ごとのライセンスで €199 から提供され、完全なソースコードと 1 年間のアップデートが付属します。sgcUI にも含まれています。

QuickReport のクラスと sgcReports の対応

以下の sgcReports の名前はすべて製品のソースコードにあり、デモで使っているものはそのままコンパイルできます。QuickReport の名前は参考として示すもので、このページを確認した時点では QuickReport はインストールしていませんでした。

QuickReport sgcReports エディション
TQuickRepTsgcReport (Pages、Styles、Units、Title) と TsgcReportEngine (Report、AddDataSource、Prepare、Variables、OnGetVariable)すべて
TQuickRep.DataSetAddDataSource で登録した TsgcReportDataSetSource (SourceName、DataSet)。バンドの DataSourceName がその名前を指定しますすべて
TQuickRep.Page (用紙、余白)TsgcReportPage.PaperSize (rpsA3, rpsA4, rpsA5, rpsLetter, rpsLegal, rpsCustom), Margins.Left, Top, Right, Bottomすべて
TQuickRep.ReportTitleTsgcReport.Title。PDF のメタデータには TsgcReportPDFExport.Titleすべて
BandType が rbTitle、rbPageHeader、rbColumnHeader の TQRBandBandType が rbtReportTitle、rbtPageHeader、rbtColumnHeader の TsgcReportBandすべて
rbDetailマスターソースを指定した DataSourceName を持つ rbtMasterDataすべて
rbGroupHeader, rbGroupFooterrbtGroupHeader, rbtGroupFooterすべて
rbSummary, rbPageFooterrbtReportSummary, rbtPageFooterすべて
TQRChildBandTsgcReportBand.ChildBandName を持つ rbtChildすべて
TQRSubDetailrbtDetailData バンド (DataSourceName = 詳細ソース)、および詳細側の TsgcReportDataSetSource の MasterSource、MasterFields、DetailFieldsすべて
TQRGroup.ExpressionGroupExpression を持つ rbtGroupHeaderすべて
TQRGroup.ReprintOnNewPageTsgcReportBand.RepeatOnEveryPageすべて
TQRGroup.FooterBand次の rbtGroupFooter バンド。最初のフッターが最も内側のグループを閉じますすべて
TQRBand.ForceNewPageTsgcReportBand.StartNewPageすべて
TQRLabel (Caption)Kind = rikText とリテラルの Text.Text を持つ項目すべて
TQRDBText (DataField, Mask)Text.Text = '[Source.Field]' の rikText。Mask は Text.DisplayFormat になりますすべて
TQRExpr (Expression)'[expression]' を使う rikText。たとえば '[Lines.Qty * Lines.Price]'。IIF、FormatFloat、FormatDateTime、Round、Upper などの関数も使えますすべて
SUM、COUNT、AVERAGE、MIN、MAX を使う TQRExpr[Sum(x)]、[Count()]、[Avg(x)]、[Min(x)]、[Max(x)]。グループフッターではグループごとにリセットされ、ページフッターではページ単位になりますすべて
TQRSysData qrsPageNumber[Page]。「Page X of Y」には [TotalPages]すべて
TQRSysData qrsDate, qrsTime, qrsDetailNoText.DisplayFormat を指定した [Date]、[Time]。[Line] または [RecNo]すべて
TQRShape (qrsRectangle, qrsCircle, qrsRoundRect)Shape.ShapeKind が rskRectangle、rskEllipse、rskRoundRect の rikShape。Shape.PenColor、FillColor、PenWidthすべて
TQRShape qrsHorLineHeight = 0 の rikLineすべて
TQRImage, TQRDBImageImage.FileName、Image.Picture、Image.DataField のいずれかを指定した rikImage。Stretch、KeepAspectRatioすべて
TQRRichText, TQRDBRichTextRichText.Markup を持つ rikRichText。RTF ではなく HTML 風のマークアップで、[expressions] を含めることもできますすべて
実行時に設定する Enabled、BeforePrint イベントバンドと項目の VisibleExpression。TsgcReportEngine.OnBeforePrintBandすべて
Prepare, PreviewTsgcReportEngine.Prepare は TsgcReportPreparedPages を返します。TsgcReportPreviewVCL.Prepare はそれらをフォーム上のコントロールに表示しますすべて
Print, PrinterSetup標準の TPrintDialog の後に呼ぶ TsgcReportPreviewVCL.Print(aTitle)すべて
PDF フィルターを指定した ExportToFilterTsgcReportPDFExport.SaveToFile(aPages, aFileName) または SaveToStreamすべて
PDF/ATsgcReportPDFExport.PDFA = rpaA3b、rpaA3a、rpaA4すべて
記載なしPDF/UA: TsgcReportPDFExport.PDFUA (既定は True)、PDFUAPart、Language、Title。項目の TagRole と AltTextすべて
記載なし (QRDesign はサードパーティ製のアドオンでした)エンドユーザー向けデザイナー: sgcShowReportDesigner、TsgcVCLReportDesigner。FireMonkey では sgcShowReportDesignerFMXRegistered

コンパイル済みデモのコード

各コード抜粋は MigrateFromQuickReport デモからコピーしたもので、Delphi 7 と Delphi 13 (Win32 と Win64) および Community エディションでコンパイルできます。コメントには、置き換える QuickReport のコードを記しています。

TQuickRep はレポートとエンジンになります

移行前: フォーム上の TQuickRep が、レポートとそのデータを 1 つのコンポーネントで保持します。移行後: レイアウト、エンジン、プレビューは別々のコンポーネントです。

frmMain.dfm
object sgcPreview: TsgcReportPreviewVCL
  Left = 0
  Top = 44
  Width = 900
  Height = 676
  Align = alClient
  TabOrder = 1
  Engine = sgcEngine
end
object sgcReport: TsgcReport
  Left = 40
  Top = 80
end
object sgcEngine: TsgcReportEngine
  Report = sgcReport
  Left = 120
  Top = 80
end

TQuickRep.DataSet と TQRSubDetail はデータソースになります

移行前: 請求書用の TQuickRep.DataSet と、明細行用に独自の DataSet を持つ TQRSubDetail。移行後: データセットごとに 1 つのソースを用意し、詳細はフィールドでマスターに結び付けます。FormCreate で両方を sgcEngine.AddDataSource に登録します。

frmMain.dfm
object srcInvoices: TsgcReportDataSetSource
  SourceName = 'Invoices'
  DataSet = cdsInvoices
  Left = 40
  Top = 208
end
object srcLines: TsgcReportDataSetSource
  SourceName = 'Lines'
  MasterSource = srcInvoices
  MasterFields = 'Number'
  DetailFields = 'Invoice'
  DataSet = cdsLines
  Left = 120
  Top = 208
end

TQRLabel、TQRDBText、TQRExpr に代わるヘルパー

デモでは、以下の抜粋を短くするために、フォームのこの小さなメソッドですべてのテキストを追加しています。

frmMain.pas
function TformMain.AddText(aBand: TsgcReportBand; const aText: string;
  aLeft, aTop, aWidth: Double; const aStyle: string): TsgcReportItem;
var
  oStyle: TsgcReportStyle;
begin
  // one item replaces TQRLabel (literal text), TQRDBText ([Source.Field])
  // and TQRExpr ([expression]); literal text and [expressions] can be mixed
  Result := aBand.Items.Add;
  Result.Kind := rikText;
  Result.Name := aBand.Name + IntToStr(aBand.Items.Count);
  Result.Text.Text := aText;
  Result.Left := aLeft;
  Result.Top := aTop;
  Result.Width := aWidth;
  Result.Height := 14;
  Result.StyleName := aStyle;
  oStyle := sgcReport.Styles.FindStyle(aStyle);
  if Assigned(oStyle) and (oStyle.Font.Size * 1.25 > Result.Height) then
    Result.Height := oStyle.Font.Size * 1.25;
end;

ページ設定、タイトルバンド、TQRSysData

移行前: TQuickRep.Page、タイトルバンド、日付を表示する TQRSysData。移行後: TagRole によって、PDF/UA のタグツリーでタイトルが見出しとして示されます。

frmMain.pas
// QuickReport: TQuickRep.Page (PaperSize, LeftMargin, TopMargin, ...)
oPage := sgcReport.Pages.Add;
oPage.Name := 'Invoices';
oPage.PaperSize := rpsA4;
oPage.Margins.Left := 40;
oPage.Margins.Top := 40;
oPage.Margins.Right := 40;
oPage.Margins.Bottom := 40;

// TQRBand BandType = rbTitle: printed once, on the first page
oBand := AddBand(oPage, rbtReportTitle, 'Title', 40);
AddText(oBand, 'Invoices by customer', 0, 0, 350, 'Title').TagRole :=
  rtrHeading1;
AddText(oBand, 'Printed on', 315, 6, 120, 'Right');
// TQRSysData Data = qrsDate
oItem := AddText(oBand, '[Date]', 440, 6, 75, 'Right');
oItem.Text.DisplayFormat := 'yyyy-mm-dd';

TQRGroup、詳細バンド、TQRSubDetail

移行前: 得意先の TQRGroup、TQRDBText コントロールの詳細バンド、明細金額の TQRExpr を持つ TQRSubDetail。移行後:

frmMain.pas
// TQRGroup Expression = 'Invoices.Customer', ReprintOnNewPage = True.
// The column titles are TQRLabel components in QuickReport
oBand := AddBand(oPage, rbtGroupHeader, 'CustomerHeader', 42);
oBand.GroupExpression := 'Invoices.Customer';
oBand.RepeatOnEveryPage := True;
AddText(oBand, '[Invoices.Customer]', 0, 4, 515, 'Group').TagRole :=
  rtrHeading2;
AddText(oBand, 'Invoice / product', 0, 24, 200, 'Bold');
AddText(oBand, 'Date / qty', 210, 24, 120, 'Bold');
AddText(oBand, 'Price', 345, 24, 70, 'BoldRight');
AddText(oBand, 'Amount', 425, 24, 90, 'BoldRight');
AddLine(oBand, 40);

// TQRBand BandType = rbDetail: one band per record of TQuickRep.DataSet.
// Each [Source.Field] text item replaces a TQRDBText with DataField set
oBand := AddBand(oPage, rbtMasterData, 'Invoice', 18);
oBand.DataSourceName := 'Invoices';
AddText(oBand, '[Invoices.Number]', 0, 3, 200, 'Bold');
oItem := AddText(oBand, '[Invoices.InvoiceDate]', 210, 3, 120, 'Bold');
oItem.Text.DisplayFormat := 'yyyy-mm-dd';
oItem := AddText(oBand, '[Invoices.Amount]', 425, 3, 90, 'BoldRight');
// TQRDBText.Mask
oItem.Text.DisplayFormat := '#,##0.00';

// TQRSubDetail DataSet = Lines, linked to the invoice: the link is
// MasterSource / MasterFields / DetailFields of srcLines (see the form)
oBand := AddBand(oPage, rbtDetailData, 'Line', 14);
oBand.DataSourceName := 'Lines';
AddText(oBand, '[Lines.Product]', 15, 1, 195);
AddText(oBand, '[Lines.Qty]', 210, 1, 40, 'Right');
oItem := AddText(oBand, '[Lines.Price]', 345, 1, 70, 'Right');
oItem.Text.DisplayFormat := '#,##0.00';
// TQRExpr Expression = 'Lines.Qty * Lines.Price'
oItem := AddText(oBand, '[Lines.Qty * Lines.Price]', 425, 1, 90, 'Right');
oItem.Text.DisplayFormat := '#,##0.00';

グループフッターの集計

移行前: グループフッターバンドの、COUNT と SUM を使う TQRExpr コンポーネント。移行後:

frmMain.pas
// TQRBand BandType = rbGroupFooter (TQRGroup.FooterBand). Aggregates are
// reset for every group, like TQRExpr with ResetAfterPrint = True
oBand := AddBand(oPage, rbtGroupFooter, 'CustomerFooter', 30);
AddLine(oBand, 2);
// TQRExpr Expression = 'COUNT' and 'SUM(Lines.Qty)'
AddText(oBand, '[Count()] invoices, [Sum(Lines.Qty)] items', 0, 8,
  250, 'Bold');
AddText(oBand, 'Customer total', 260, 8, 155, 'BoldRight');
// TQRExpr Expression = 'SUM(Invoices.Amount)'
oItem := AddText(oBand, '[Sum(Invoices.Amount)]', 425, 8, 90, 'BoldRight');
oItem.Text.DisplayFormat := '#,##0.00';

サマリーバンド、TQRShape、TQRRichText

移行前: TQRShape、総合計、TQRRichText を持つサマリーバンド。移行後: リッチテキストは HTML 風のマークアップです。

frmMain.pas
// TQRBand BandType = rbSummary: printed once, after the last record
oBand := AddBand(oPage, rbtReportSummary, 'Summary', 90);
oBand.KeepTogether := True;
// TQRShape Shape = qrsRectangle, Brush.Color and Pen.Color
oItem := oBand.Items.Add;
oItem.Kind := rikShape;
oItem.Name := 'SummaryBox';
oItem.Top := 10;
oItem.Width := 515;
oItem.Height := 30;
oItem.Shape.ShapeKind := rskRectangle;
oItem.Shape.PenColor := $00A0A0A0;
oItem.Shape.FillColor := $00EEF3FA;
// TQRExpr Expression = 'COUNT' and 'SUM(Invoices.Amount)' in the summary
AddText(oBand, 'Grand total, [Count()] invoices', 10, 17, 300, 'Group');
oItem := AddText(oBand, '[Sum(Invoices.Amount)]', 315, 17, 190,
  'GroupRight');
oItem.Text.DisplayFormat := '#,##0.00';
// TQRRichText: the text is HTML-like markup instead of RTF
oItem := oBand.Items.Add;
oItem.Kind := rikRichText;
oItem.Name := 'SummaryNote';
oItem.Top := 50;
oItem.Width := 515;
oItem.Height := 36;
oItem.StyleName := 'Base';
oItem.RichText.Markup := '<b>Migrated from QuickReport.</b> Each band of ' +
  'this report replaces a <i>TQRBand</i>, each text item a <i>TQRLabel</i>, '
  + '<i>TQRDBText</i> or <i>TQRExpr</i>.';

Page X of Y を表示するページフッター

frmMain.pas
// TQRBand BandType = rbPageFooter
oBand := AddBand(oPage, rbtPageFooter, 'PageFooter', 20);
AddLine(oBand, 2);
// TQRLabel with a literal caption
AddText(oBand, 'Invoices by customer', 0, 6, 300);
// TQRSysData Data = qrsPageNumber; [TotalPages] is resolved after the
// last page is laid out
AddText(oBand, 'Page [Page] of [TotalPages]', 315, 6, 200, 'Right');

プレビューと印刷

移行前: QuickRep1.Preview、PrinterSetup、Print。移行後:

frmMain.pas
procedure TformMain.btnPreviewClick(Sender: TObject);
begin
  // QuickReport: QuickRep1.Preview (or Prepare + a TQRPreview). sgcReports:
  // the preview control on the form runs the engine and shows the pages
  sgcPreview.Prepare;
  lblStatus.Caption := Format('%d pages prepared', [sgcPreview.PageCount]);
end;

procedure TformMain.btnPrintClick(Sender: TObject);
begin
  // QuickReport: QuickRep1.PrinterSetup + QuickRep1.Print. The print dialog
  // selects the printer, Print sends the prepared pages to it
  if dlgPrint.Execute then
    sgcPreview.Print(sgcReport.Title);
end;

ExportToFilter は TsgcReportPDFExport になります

移行前: PDF フィルターを指定した ExportToFilter。移行後: 1 つのスイッチで、通常の PDF かタグ付き PDF/UA ファイルを出力します。

frmMain.pas
procedure TformMain.SavePDF(aPDFUA: Boolean; const aFileName: string);
var
  oPages: TsgcReportPreparedPages;
  vFileName: string;
begin
  // QuickReport: QuickRep1.ExportToFilter(TQRPDFDocumentFilter.Create(...))
  vFileName := ExtractFilePath(ParamStr(0)) + aFileName;
  // PDF/UA: a tagged PDF (headings, reading order, alternate texts); Title
  // and Language are set on pdfExport in the form
  pdfExport.PDFUA := aPDFUA;
  oPages := sgcEngine.Prepare;
  try
    pdfExport.SaveToFile(oPages, vFileName);
  finally
    oPages.Free;
  end;
  lblStatus.Caption := Format('Saved %s (%d warnings)',
    [vFileName, pdfExport.Warnings.Count]);
end;

レポートごとの 8 つの手順

データセットはそのままです。レポートはバンドごとに作り直します。

1

TQuickRep を置き換える

通常のフォームに、TsgcReport、TsgcReportEngine (Report = そのレポート)、TsgcReportPreviewVCL (Engine = そのエンジン) を配置します。

2

データを登録する

データセットごとに TsgcReportDataSetSource (SourceName、DataSet) を追加し、AddDataSource を呼び出します。TQRSubDetail ごとに MasterSource、MasterFields、DetailFields を設定します。

3

ページを設定する

TQuickRep.Page の用紙サイズと余白を指定した TsgcReportPage を追加し、座標が予測しやすいように TsgcReport.Units (デモでは ruPoints) を設定します。

4

バンドを作り直す

TQRBand ごとに TsgcReportBand を 1 つ、レポートの順に、対応する rbt のバンド種類で作成します。マスターと詳細のバンドには DataSourceName、グループヘッダーには GroupExpression を設定します。

5

コントロールを作り直す

TQRLabel、TQRDBText、TQRExpr は、リテラルテキストと [expressions] を組み合わせた rikText 項目になります。Mask は Text.DisplayFormat に、フォントは名前付きスタイルになります。

6

式を置き換える

集計は [Sum(x)]、[Count()]、[Avg(x)]、[Min(x)]、[Max(x)] になり、TQRSysData は [Page]、[TotalPages]、[Date]、[Time] になります。

7

プレビュー、印刷、エクスポート

Preview は TsgcReportPreviewVCL.Prepare、Print は Print、PDF フィルターは TsgcReportPDFExport.SaveToFile になります。アクセシブルな PDF にするには PDFUA、Title、Language を設定します。

8

ユーザーに渡す

任意 (Registered エディション): 作り直したレポートを TsgcReport.SaveToFile で JSON として保存し、ユーザーが sgcShowReportDesigner で編集できるようにします。

1 対 1 では対応しない点

移行を計画する前にお読みください。

MigrateFromQuickReport

典型的な QuickReport のマスター詳細形式の請求書一覧を得意先ごとにグループ化したものです。4 社の請求書 18 件とその明細行を、コードで埋めた 2 つの TClientDataSet から作ります。

場所

sgcUI のインストーラーは Demos\Reports\Delphi\MigrateFromQuickReport に配置します。内容は sgcReports_Demo_MigrateFromQuickReport.dpr、frmMain.pas、frmMain.dfm、readme.html です。Community エディションにも含まれます。

実行方法

sgcReports と sgcPDF をインストールした Delphi 7 から 13 のいずれかで .dpr を開き、Win32 または Win64 でビルドして実行します。レポートは起動時に作成され、「Page X of Y」付きの 3 ページになります。

試すこと

Print... は印刷ダイアログを表示して印刷します。Save PDF は invoices.pdf を、Save PDF/UA はタグ付きの invoices_pdfua.pdf を exe と同じ場所に書き出します。PDF/UA バリデーターでそのまま検証できます。

両方のエンジンに公平を期すために述べると、QuickReport は再びメンテナンスされ、Delphi 7 以降をサポートし、レポートは Delphi のフォームデザイナーで設計します。機能ページには XML/XSLT など、sgcReports にはないエクスポートフィルターが載っており、QuickReport を使い続ければレポートを作り直す必要はありません。アクセシブルな PDF/UA 出力、ユーザー向けのデザイナー、sgcCharts や sgcPivotGrid や .NET サービスと共有するレポートが必要で、各レポートを 1 回作り直すことを受け入れられるなら、sgcReports が進むべき道です。機能の一覧は sgcReports の製品ページをご覧ください。

最もお得な選択: All-AccesseSeGeCe の全製品にプレミアムサポートが付いて、年間 €1,059 からご利用いただけます。
All-Access の価格を見る

最初のレポートを今日から作り直す

sgcReports と MigrateFromQuickReport デモを含む sgcUI 体験版をダウンロードして、最初のレポートを移行しましょう。