Migrate from QuickReport to sgcReports

sgcReports is the band report engine of sgcUI: TsgcReport holds the layout, TsgcReportEngine binds the data, TsgcReportPreviewVCL shows the pages, and the PDF export writes tagged PDF/UA. This kit maps the QuickReport bands and controls you use to their sgcReports twins, shows the code from a compiled demo, and lists honestly what does not map.

Delphi VCL Reports Built With QuickReport

A TQuickRep on a form, bands, QR controls on the bands, and a preview, print or PDF button in the application.

QuickReport is maintained again. In "QuickReport is back" (Embarcadero blog, Ian Barker, 14 November 2024) Embarcadero explains that the product hit a crisis when its lead developer passed away, that it was brought back with the Embarcadero partner Barnsten, and that it now supports every version of RAD Studio with Delphi and C++Builder from Delphi 7. The Barnsten QuickReport page (read on 2026-10-20) lists a PDF filter with embedded TrueType fonts, PDF/A support, and HTML, XML/XSLT, XLS and XLSX export filters, and prices QuickReport Pro 5-developer at EUR 2.155,00 excluding VAT. So this page is not about a dead product or a missing PDF button. It is for teams that want what that feature list does not name.

What sgcReports Adds

Every sgcReports claim below is in the shipped source. The QuickReport side says "not listed" where the vendor page is silent, not "not supported".

Accessible PDF/UA

TsgcReportPDFExport writes tagged PDF/UA by default (PDFUA is True, PDFUAPart picks part 1 or 2), with a reading order, heading roles from the item TagRole, alternate texts from AltText, and the document Language and Title. PDFA adds PDF/A-3b, PDF/A-3a or PDF/A-4 for archives. It is in every edition, Community included. PDF/UA and tagged PDF are not listed on the Barnsten feature page. Accessible documents matter more since the European Accessibility Act, Directive (EU) 2019/882, which covers products and services such as e-books, e-commerce and banking services.

An end user designer, VCL and FireMonkey

Your users can change a report without a new build: sgcShowReportDesigner(Engine) opens the VCL designer, or embed the TsgcVCLReportDesigner panel; sgcShowReportDesignerFMX(Engine) does the same in FireMonkey (Delphi XE6 and later, desktop). The VCL designer follows DPI changes of the form (its inspector, icons and design surface rescale in ChangeScale). Registered editions only. The Barnsten feature page does not list an end user designer; historically that was a separate third party product, QRDesign. On High DPI, a Delphi-PRAXiS reply of 4 April 2022 said QuickReport 6 builds with Delphi 11.1 but does not support High-DPI; check the current release with the vendor.

One engine for the suite

Crosstabs, barcodes, subreports and rich text are item kinds of the same band engine. With the bridge units, a report also prints an sgcCharts chart and an sgcPivotGrid pivot table as items, drawn as vector content in the PDF (Registered editions). Exports: PDF, XLSX, CSV, HTML and PNG in every edition, DOCX in the Registered editions.

JSON definitions, and a .NET counterpart

A report saves to and loads from JSON (TsgcReport.SaveToFile, LoadFromFile), so layouts can live in a database or in version control. The same definition loads in sgcReports for .NET (NuGet esegece.sgcReports, .NET Standard 2.0, .NET Framework 4.7.2 and .NET 6 and later), so a Delphi report can be reused by a .NET service.

Reports are rebuilt, not imported. sgcReports cannot open a QuickReport .dfm: there is no QuickReport importer. Each report is recreated, in code as the demo below does, or in the sgcReports designer (Registered editions). The mapping and the steps on this page make that a mechanical job, band by band. sgcReports is licensed per developer from €199 with full source code and one year of updates, and it is also part of sgcUI.

QuickReport Classes, sgcReports Equivalents

Every sgcReports name below is in the shipped source, and the ones the demo uses compile in it. The QuickReport names are given for orientation; QuickReport was not installed when this page was checked.

QuickReport sgcReports Edition
TQuickRepTsgcReport (Pages, Styles, Units, Title) and TsgcReportEngine (Report, AddDataSource, Prepare, Variables, OnGetVariable)All
TQuickRep.DataSetTsgcReportDataSetSource (SourceName, DataSet) registered with AddDataSource; the band DataSourceName names itAll
TQuickRep.Page (paper, margins)TsgcReportPage.PaperSize (rpsA3, rpsA4, rpsA5, rpsLetter, rpsLegal, rpsCustom), Margins.Left, Top, Right, BottomAll
TQuickRep.ReportTitleTsgcReport.Title, and TsgcReportPDFExport.Title for the PDF metadataAll
TQRBand with BandType rbTitle, rbPageHeader, rbColumnHeaderTsgcReportBand with BandType rbtReportTitle, rbtPageHeader, rbtColumnHeaderAll
rbDetailrbtMasterData with DataSourceName set to the master sourceAll
rbGroupHeader, rbGroupFooterrbtGroupHeader, rbtGroupFooterAll
rbSummary, rbPageFooterrbtReportSummary, rbtPageFooterAll
TQRChildBandrbtChild with TsgcReportBand.ChildBandNameAll
TQRSubDetailAn rbtDetailData band (DataSourceName = detail source) and MasterSource, MasterFields, DetailFields on the detail TsgcReportDataSetSourceAll
TQRGroup.ExpressionrbtGroupHeader with GroupExpressionAll
TQRGroup.ReprintOnNewPageTsgcReportBand.RepeatOnEveryPageAll
TQRGroup.FooterBandThe next rbtGroupFooter band; the first footer closes the innermost groupAll
TQRBand.ForceNewPageTsgcReportBand.StartNewPageAll
TQRLabel (Caption)An item with Kind = rikText and literal Text.TextAll
TQRDBText (DataField, Mask)rikText with Text.Text = '[Source.Field]'; Mask becomes Text.DisplayFormatAll
TQRExpr (Expression)rikText with '[expression]', for example '[Lines.Qty * Lines.Price]'; functions such as IIF, FormatFloat, FormatDateTime, Round, UpperAll
TQRExpr with SUM, COUNT, AVERAGE, MIN, MAX[Sum(x)], [Count()], [Avg(x)], [Min(x)], [Max(x)]; reset per group in group footers, page scope in page footersAll
TQRSysData qrsPageNumber[Page], and [TotalPages] for Page X of YAll
TQRSysData qrsDate, qrsTime, qrsDetailNo[Date], [Time] with Text.DisplayFormat; [Line] or [RecNo]All
TQRShape (qrsRectangle, qrsCircle, qrsRoundRect)rikShape with Shape.ShapeKind rskRectangle, rskEllipse, rskRoundRect; Shape.PenColor, FillColor, PenWidthAll
TQRShape qrsHorLinerikLine with Height = 0All
TQRImage, TQRDBImagerikImage with Image.FileName or Image.Picture, or Image.DataField; Stretch, KeepAspectRatioAll
TQRRichText, TQRDBRichTextrikRichText with RichText.Markup: HTML-like markup, not RTF, and it may contain [expressions]All
Enabled set at run time, BeforePrint eventsVisibleExpression on bands and items; TsgcReportEngine.OnBeforePrintBandAll
Prepare, PreviewTsgcReportEngine.Prepare returns TsgcReportPreparedPages; TsgcReportPreviewVCL.Prepare shows them in a control on the formAll
Print, PrinterSetupTsgcReportPreviewVCL.Print(aTitle), after a standard TPrintDialogAll
ExportToFilter with a PDF filterTsgcReportPDFExport.SaveToFile(aPages, aFileName) or SaveToStreamAll
PDF/ATsgcReportPDFExport.PDFA = rpaA3b, rpaA3a or rpaA4All
Not listedPDF/UA: TsgcReportPDFExport.PDFUA (default True), PDFUAPart, Language, Title; item TagRole and AltTextAll
Not listed (QRDesign was a third party add on)End user designer: sgcShowReportDesigner, TsgcVCLReportDesigner; sgcShowReportDesignerFMX in FireMonkeyRegistered

The Code, From the Compiled Demo

Each excerpt is copied from the MigrateFromQuickReport demo, which compiles with Delphi 7 and Delphi 13 (Win32 and Win64) and in the Community edition. The comments name the QuickReport code it replaces.

TQuickRep becomes a report and an engine

Before: a TQuickRep on the form, with the report and its data in one component. After: the layout, the engine and the preview are separate components.

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 and TQRSubDetail become data sources

Before: TQuickRep.DataSet for the invoices and a TQRSubDetail with its own DataSet for the lines. After: one source per dataset, the detail linked to the master by fields. FormCreate registers both with 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

A helper that replaces TQRLabel, TQRDBText and TQRExpr

The demo adds every text with this small method of its form, so the excerpts below stay short.

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;

Page setup, the title band and TQRSysData

Before: TQuickRep.Page, a title band and a TQRSysData with the date. After: TagRole marks the title as a heading in the PDF/UA tag tree.

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, the detail band and TQRSubDetail

Before: a TQRGroup on the customer, a detail band of TQRDBText controls, and a TQRSubDetail with a TQRExpr for the line amount. After:

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';

Before: TQRExpr components with COUNT and SUM in the group footer band. After:

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';

The summary band, TQRShape and TQRRichText

Before: a summary band with a TQRShape, grand totals and a TQRRichText. After: the rich text is HTML-like markup.

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>.';
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');

Preview and print

Before: QuickRep1.Preview, PrinterSetup and Print. After:

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 becomes TsgcReportPDFExport

Before: ExportToFilter with a PDF filter. After: one switch writes a plain PDF or a tagged PDF/UA file.

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;

Eight Steps per Report

The datasets stay as they are. The report is rebuilt band by band.

1

Replace the TQuickRep

Put a TsgcReport, a TsgcReportEngine (Report = the report) and a TsgcReportPreviewVCL (Engine = the engine) on a normal form.

2

Register the data

Add a TsgcReportDataSetSource per dataset (SourceName, DataSet) and call AddDataSource. For each TQRSubDetail set MasterSource, MasterFields and DetailFields.

3

Set up the page

Add a TsgcReportPage with the paper size and margins of TQuickRep.Page, and set TsgcReport.Units (ruPoints in the demo) so the coordinates are predictable.

4

Recreate the bands

One TsgcReportBand per TQRBand, in report order, with the matching rbt band type; DataSourceName on master and detail bands, GroupExpression on group headers.

5

Recreate the controls

TQRLabel, TQRDBText and TQRExpr become rikText items that mix literal text and [expressions]. Mask becomes Text.DisplayFormat, fonts become named styles.

6

Translate the expressions

Aggregates become [Sum(x)], [Count()], [Avg(x)], [Min(x)] and [Max(x)]; TQRSysData becomes [Page], [TotalPages], [Date] and [Time].

7

Preview, print, export

Preview becomes TsgcReportPreviewVCL.Prepare, Print becomes Print, and the PDF filter becomes TsgcReportPDFExport.SaveToFile. Set PDFUA, Title and Language for an accessible PDF.

8

Hand it to your users

Optional, Registered editions: save the rebuilt report as JSON with TsgcReport.SaveToFile and let users edit it with sgcShowReportDesigner.

What Does Not Map One to One

Read this before you plan the move.

MigrateFromQuickReport

A typical QuickReport master detail invoice list, grouped by customer: 18 invoices of 4 customers and their lines, from two TClientDataSet filled in code.

Where it is

The sgcUI installer puts it in Demos\Reports\Delphi\MigrateFromQuickReport: sgcReports_Demo_MigrateFromQuickReport.dpr, frmMain.pas, frmMain.dfm and a readme.html. It is in the Community edition too.

How to run it

Open the .dpr in any Delphi from 7 to 13 with sgcReports and sgcPDF installed, build Win32 or Win64 and run. The report is prepared on start, three pages with Page X of Y.

What to try

Print... shows a print dialog and prints. Save PDF writes invoices.pdf and Save PDF/UA writes the tagged invoices_pdfua.pdf next to the exe, ready for a check with a PDF/UA validator.

To be fair to both engines: QuickReport is maintained again, supports Delphi 7 onwards, and its reports are designed in the Delphi form designer. Its feature page lists export filters, such as XML/XSLT, that sgcReports does not have, and keeping it means no report has to be rebuilt. sgcReports is the path when you need accessible PDF/UA output, a designer for your users, reports shared with sgcCharts, sgcPivotGrid or a .NET service, and you accept rebuilding each report once. For the full feature list see the sgcReports product page.

Best value: All-AccessEvery eSeGeCe product, Premium Support included, from €1,059/year.
See All-Access pricing

Rebuild Your First Report Today

Download the sgcUI trial with sgcReports and the MigrateFromQuickReport demo, and port your first report.