Migreer van QuickReport naar sgcReports

sgcReports is de bandrapportengine van sgcUI: TsgcReport bevat de indeling, TsgcReportEngine bindt de data, TsgcReportPreviewVCL toont de pagina's en de PDF-export schrijft getagde PDF/UA. Deze kit koppelt de QuickReport-banden en -besturingselementen die je gebruikt aan hun sgcReports-tegenhangers, toont de code uit een gecompileerde demo en noemt eerlijk wat niet past.

Delphi VCL-rapporten gebouwd met QuickReport

Een TQuickRep op een formulier, banden, QR-besturingselementen op de banden, en een knop voor voorbeeld, afdrukken of PDF in de applicatie.

QuickReport wordt weer onderhouden. In "QuickReport is back" (Embarcadero-blog, Ian Barker, 14 november 2024) legt Embarcadero uit dat het product in een crisis belandde toen de hoofdontwikkelaar overleed, dat het is teruggebracht met de Embarcadero-partner Barnsten, en dat het nu elke versie van RAD Studio met Delphi en C++Builder ondersteunt vanaf Delphi 7. De Barnsten QuickReport-pagina (gelezen op 2026-10-20) vermeldt een PDF-filter met ingebedde TrueType-lettertypen, PDF/A-ondersteuning, en exportfilters voor HTML, XML/XSLT, XLS en XLSX, en rekent voor QuickReport Pro 5-developer EUR 2.155,00 exclusief btw. Deze pagina gaat dus niet over een dood product of een ontbrekende PDF-knop. Ze is bedoeld voor teams die willen wat die functielijst niet noemt.

Wat sgcReports toevoegt

Elke bewering over sgcReports hieronder staat in de meegeleverde broncode. Aan de QuickReport-kant staat "niet vermeld" waar de pagina van de leverancier zwijgt, niet "niet ondersteund".

Toegankelijke PDF/UA

TsgcReportPDFExport schrijft standaard getagde PDF/UA (PDFUA is True, PDFUAPart kiest deel 1 of 2), met een leesvolgorde, koprollen uit de item-TagRole, alternatieve teksten uit AltText, en de documenttaal Language en Title. PDFA voegt PDF/A-3b, PDF/A-3a of PDF/A-4 toe voor archieven. Het zit in elke editie, ook Community. PDF/UA en getagde PDF worden niet vermeld op de functiepagina van Barnsten. Toegankelijke documenten zijn belangrijker sinds de European Accessibility Act, Richtlijn (EU) 2019/882, die producten en diensten zoals e-books, e-commerce en bankdiensten omvat.

Een ontwerper voor eindgebruikers, VCL en FireMonkey

Je gebruikers kunnen een rapport wijzigen zonder nieuwe build: sgcShowReportDesigner(Engine) opent de VCL-ontwerper, of sluit het paneel TsgcVCLReportDesigner in; sgcShowReportDesignerFMX(Engine) doet hetzelfde in FireMonkey (Delphi XE6 en later, desktop). De VCL-ontwerper volgt DPI-wijzigingen van het formulier (inspector, pictogrammen en ontwerpoppervlak schalen mee in ChangeScale). Alleen geregistreerde edities. De functiepagina van Barnsten vermeldt geen ontwerper voor eindgebruikers; historisch was dat een apart product van een derde partij, QRDesign. Over High DPI zei een antwoord op Delphi-PRAXiS van 4 april 2022 dat QuickReport 6 bouwt met Delphi 11.1 maar High-DPI niet ondersteunt; controleer de huidige release bij de leverancier.

Eén engine voor de hele suite

Kruistabellen, streepjescodes, subrapporten en rich text zijn itemsoorten van dezelfde bandengine. Met de brugunits drukt een rapport ook een sgcCharts-grafiek en een sgcPivotGrid-draaitabel af als items, getekend als vectorinhoud in de PDF (geregistreerde edities). Exports: PDF, XLSX, CSV, HTML en PNG in elke editie, DOCX in de geregistreerde edities.

JSON-definities en een .NET-tegenhanger

Een rapport wordt opgeslagen in en geladen uit JSON (TsgcReport.SaveToFile, LoadFromFile), dus indelingen kunnen in een database of in versiebeheer leven. Dezelfde definitie laadt in sgcReports voor .NET (NuGet esegece.sgcReports, .NET Standard 2.0, .NET Framework 4.7.2 en .NET 6 en hoger), zodat een Delphi-rapport door een .NET-service kan worden hergebruikt.

Rapporten worden opnieuw opgebouwd, niet geïmporteerd. sgcReports kan geen QuickReport-.dfm openen: er is geen QuickReport-importer. Elk rapport wordt opnieuw gemaakt, in code zoals de demo hieronder doet, of in de sgcReports-ontwerper (geregistreerde edities). De mapping en de stappen op deze pagina maken daar een mechanische klus van, band voor band. sgcReports wordt per ontwikkelaar gelicentieerd vanaf €199 met volledige broncode en één jaar updates, en maakt ook deel uit van sgcUI.

QuickReport-klassen, sgcReports-equivalenten

Elke sgcReports-naam hieronder staat in de meegeleverde broncode, en de namen die de demo gebruikt compileren erin. De QuickReport-namen dienen ter oriëntatie; QuickReport was niet geïnstalleerd toen deze pagina werd gecontroleerd.

QuickReport sgcReports Editie
TQuickRepTsgcReport (Pages, Styles, Units, Title) en TsgcReportEngine (Report, AddDataSource, Prepare, Variables, OnGetVariable)Alle
TQuickRep.DataSetTsgcReportDataSetSource (SourceName, DataSet) geregistreerd met AddDataSource; de band-DataSourceName noemt hemAlle
TQuickRep.Page (papier, marges)TsgcReportPage.PaperSize (rpsA3, rpsA4, rpsA5, rpsLetter, rpsLegal, rpsCustom), Margins.Left, Top, Right, BottomAlle
TQuickRep.ReportTitleTsgcReport.Title, en TsgcReportPDFExport.Title voor de PDF-metadataAlle
TQRBand met BandType rbTitle, rbPageHeader, rbColumnHeaderTsgcReportBand met BandType rbtReportTitle, rbtPageHeader, rbtColumnHeaderAlle
rbDetailrbtMasterData met DataSourceName ingesteld op de masterbronAlle
rbGroupHeader, rbGroupFooterrbtGroupHeader, rbtGroupFooterAlle
rbSummary, rbPageFooterrbtReportSummary, rbtPageFooterAlle
TQRChildBandrbtChild met TsgcReportBand.ChildBandNameAlle
TQRSubDetailEen rbtDetailData-band (DataSourceName = detailbron) en MasterSource, MasterFields, DetailFields op de detail-TsgcReportDataSetSourceAlle
TQRGroup.ExpressionrbtGroupHeader met GroupExpressionAlle
TQRGroup.ReprintOnNewPageTsgcReportBand.RepeatOnEveryPageAlle
TQRGroup.FooterBandDe volgende rbtGroupFooter-band; de eerste voettekst sluit de binnenste groepAlle
TQRBand.ForceNewPageTsgcReportBand.StartNewPageAlle
TQRLabel (Caption)Een item met Kind = rikText en letterlijke Text.TextAlle
TQRDBText (DataField, Mask)rikText met Text.Text = '[Source.Field]'; Mask wordt Text.DisplayFormatAlle
TQRExpr (Expression)rikText met '[expression]', bijvoorbeeld '[Lines.Qty * Lines.Price]'; functies zoals IIF, FormatFloat, FormatDateTime, Round, UpperAlle
TQRExpr met SUM, COUNT, AVERAGE, MIN, MAX[Sum(x)], [Count()], [Avg(x)], [Min(x)], [Max(x)]; reset per groep in groepsvoetteksten, paginabereik in paginavoettekstenAlle
TQRSysData qrsPageNumber[Page], en [TotalPages] voor Pagina X van YAlle
TQRSysData qrsDate, qrsTime, qrsDetailNo[Date], [Time] met Text.DisplayFormat; [Line] of [RecNo]Alle
TQRShape (qrsRectangle, qrsCircle, qrsRoundRect)rikShape met Shape.ShapeKind rskRectangle, rskEllipse, rskRoundRect; Shape.PenColor, FillColor, PenWidthAlle
TQRShape qrsHorLinerikLine met Height = 0Alle
TQRImage, TQRDBImagerikImage met Image.FileName of Image.Picture, of Image.DataField; Stretch, KeepAspectRatioAlle
TQRRichText, TQRDBRichTextrikRichText met RichText.Markup: HTML-achtige opmaak, geen RTF, en ze mag [expressions] bevattenAlle
Enabled ingesteld tijdens runtime, BeforePrint-eventsVisibleExpression op banden en items; TsgcReportEngine.OnBeforePrintBandAlle
Prepare, PreviewTsgcReportEngine.Prepare geeft TsgcReportPreparedPages terug; TsgcReportPreviewVCL.Prepare toont ze in een besturingselement op het formulierAlle
Print, PrinterSetupTsgcReportPreviewVCL.Print(aTitle), na een standaard TPrintDialogAlle
ExportToFilter met een PDF-filterTsgcReportPDFExport.SaveToFile(aPages, aFileName) of SaveToStreamAlle
PDF/ATsgcReportPDFExport.PDFA = rpaA3b, rpaA3a of rpaA4Alle
Niet vermeldPDF/UA: TsgcReportPDFExport.PDFUA (standaard True), PDFUAPart, Language, Title; item-TagRole en AltTextAlle
Niet vermeld (QRDesign was een add-on van een derde partij)Ontwerper voor eindgebruikers: sgcShowReportDesigner, TsgcVCLReportDesigner; sgcShowReportDesignerFMX in FireMonkeyGeregistreerd

De code, uit de gecompileerde demo

Elk fragment is gekopieerd uit de MigrateFromQuickReport-demo, die compileert met Delphi 7 en Delphi 13 (Win32 en Win64) en in de Community-editie. De opmerkingen noemen de QuickReport-code die ze vervangt.

TQuickRep wordt een rapport en een engine

Voor: een TQuickRep op het formulier, met het rapport en zijn data in één component. Na: de indeling, de engine en het voorbeeld zijn aparte componenten.

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 en TQRSubDetail worden databronnen

Voor: TQuickRep.DataSet voor de facturen en een TQRSubDetail met een eigen DataSet voor de regels. Na: één bron per dataset, de detail via velden aan de master gekoppeld. FormCreate registreert beide met 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

Een hulpmethode die TQRLabel, TQRDBText en TQRExpr vervangt

De demo voegt elke tekst toe met deze kleine methode van zijn formulier, zodat de fragmenten hieronder kort blijven.

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;

Pagina-instelling, de titelband en TQRSysData

Voor: TQuickRep.Page, een titelband en een TQRSysData met de datum. Na: TagRole markeert de titel als kop in de PDF/UA-tagboom.

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, de detailband en TQRSubDetail

Voor: een TQRGroup op de klant, een detailband met TQRDBText-besturingselementen, en een TQRSubDetail met een TQRExpr voor het regelbedrag. Na:

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

Aggregaten in de groepsvoettekst

Voor: TQRExpr-componenten met COUNT en SUM in de groepsvoettekstband. Na:

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

De samenvattingsband, TQRShape en TQRRichText

Voor: een samenvattingsband met een TQRShape, eindtotalen en een TQRRichText. Na: de rich text is HTML-achtige opmaak.

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

Paginavoettekst met Pagina X van 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');

Voorbeeld en afdrukken

Voor: QuickRep1.Preview, PrinterSetup en Print. Na:

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

Voor: ExportToFilter met een PDF-filter. Na: één schakelaar schrijft een gewone PDF of een getagd PDF/UA-bestand.

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;

Acht stappen per rapport

De datasets blijven zoals ze zijn. Het rapport wordt band voor band opnieuw opgebouwd.

1

Vervang de TQuickRep

Zet een TsgcReport, een TsgcReportEngine (Report = het rapport) en een TsgcReportPreviewVCL (Engine = de engine) op een normaal formulier.

2

Registreer de data

Voeg per dataset een TsgcReportDataSetSource toe (SourceName, DataSet) en roep AddDataSource aan. Stel voor elke TQRSubDetail MasterSource, MasterFields en DetailFields in.

3

Stel de pagina in

Voeg een TsgcReportPage toe met het papierformaat en de marges van TQuickRep.Page en stel TsgcReport.Units in (ruPoints in de demo) zodat de coördinaten voorspelbaar zijn.

4

Maak de banden opnieuw

Eén TsgcReportBand per TQRBand, in rapportvolgorde, met het bijpassende bandtype rbt; DataSourceName op master- en detailbanden, GroupExpression op groepskoppen.

5

Maak de besturingselementen opnieuw

TQRLabel, TQRDBText en TQRExpr worden rikText-items die letterlijke tekst en [expressions] combineren. Mask wordt Text.DisplayFormat, lettertypen worden benoemde stijlen.

6

Vertaal de expressies

Aggregaten worden [Sum(x)], [Count()], [Avg(x)], [Min(x)] en [Max(x)]; TQRSysData wordt [Page], [TotalPages], [Date] en [Time].

7

Voorbeeld, afdrukken, exporteren

Preview wordt TsgcReportPreviewVCL.Prepare, Print wordt Print, en het PDF-filter wordt TsgcReportPDFExport.SaveToFile. Stel PDFUA, Title en Language in voor een toegankelijke PDF.

8

Geef het aan je gebruikers

Optioneel, geregistreerde edities: sla het opnieuw opgebouwde rapport op als JSON met TsgcReport.SaveToFile en laat gebruikers het bewerken met sgcShowReportDesigner.

Wat niet één op één past

Lees dit voordat je de overstap plant.

MigrateFromQuickReport

Een typische QuickReport-factuurlijst met master-detail, gegroepeerd per klant: 18 facturen van 4 klanten en hun regels, uit twee in code gevulde TClientDataSet.

Waar staat hij

Het sgcUI-installatieprogramma plaatst hem in Demos\Reports\Delphi\MigrateFromQuickReport: sgcReports_Demo_MigrateFromQuickReport.dpr, frmMain.pas, frmMain.dfm en een readme.html. Hij zit ook in de Community-editie.

Zo draai je hem

Open de .dpr in een willekeurige Delphi van 7 tot en met 13 met sgcReports en sgcPDF geïnstalleerd, bouw Win32 of Win64 en start. Het rapport wordt bij het starten voorbereid, drie pagina's met Pagina X van Y.

Wat je kunt proberen

Print... toont een afdrukdialoog en drukt af. Save PDF schrijft invoices.pdf en Save PDF/UA schrijft de getagde invoices_pdfua.pdf naast de exe, klaar voor controle met een PDF/UA-validator.

Om beide engines recht te doen: QuickReport wordt weer onderhouden, ondersteunt Delphi 7 en later, en zijn rapporten worden ontworpen in de Delphi-formulierontwerper. De functiepagina vermeldt exportfilters, zoals XML/XSLT, die sgcReports niet heeft, en wie het behoudt hoeft geen rapport opnieuw op te bouwen. sgcReports is de weg als je toegankelijke PDF/UA-uitvoer nodig hebt, een ontwerper voor je gebruikers, rapporten die met sgcCharts, sgcPivotGrid of een .NET-service worden gedeeld, en je accepteert dat je elk rapport één keer opnieuw opbouwt. Zie de productpagina van sgcReports voor de volledige functielijst.

De beste deal: All-AccessElk eSeGeCe-product, inclusief Premium-ondersteuning, vanaf €1,059 per jaar.
Bekijk de All-Access-prijzen

Bouw je eerste rapport vandaag opnieuw op

Download de sgcUI-proefversie met sgcReports en de MigrateFromQuickReport-demo, en breng je eerste rapport over.