|
Registriert seit: 8. Jan 2007 472 Beiträge |
#1
Im sechsten Artikel der mORMot Vorstellungsreihe wird gezeigt, wie mittels eines Mediators Daten im JSON-Format für die Anzeige in FastReport aufbereitet werden. Mediatoren sind eine elegante Möglichkeit Funktionalität zu kapseln und die einfache und sichere Anwendung zu erreichen. Wieder mit dabei ist die eierlegende Wollmilchsau DocVariant. Die Beispiel-Anwendung beinhaltet den Endbenutzer-Bericht-Designer von FastReport. Für alle Leser, die nur die eingeschränkte Embarcadero Edition kennen, eine Möglichkeit die Vollversion in Augenschein zu nehmen. Nicht alle Funktionen sind freigeschaltet! Die enthaltenen Verweise zur Dokumentation verlinken zur aktuell verfügbaren mORMot1 Hilfe. Für das Beispiel wird mORMot2 verwendet. Die Namen für Klassen und Funktionen können sich leicht unterscheiden.
Eins, zwei, drei, fertig ist die Bericht-Einbinderei Zumindest dann, wenn man sich Unterstützung holt. Schon die Gang of Four (GoF) hat in ihrem Buch Design Patterns von 1994 das Muster Vermittler beschrieben. Vermittler/Mediator ist im wörtlichen Sinne zutreffend. Wer schon einige Artikel von mir gelesen hat, weiß, der Mediator hat einen festen Platz im Repertoire. Oft ist das Problem, dass die gezeigten Anwendungsbeispiele unterkomplex sind. Heute zeige ich mehr Möglichkeiten am Beispiel eines Inhouse Tools. Das Beschleunigungspotenzial für die Anwendungsentwicklung lässt sich an einem ReportMediator gut darstellen. Viele sich wiederholende Schritte werden automatisch erledigt und der Objektinspektor ist außen vor. Anmerkung: Der Begriff Mediator wird im Text allgemeiner verwendet, als es der Kontext des gleichnamigen Design-Patterns vorgibt. Im Anhang befindet sich der Sourcecode und das ausführbare Programm. Der Sourcecode der Beispiel-Anwendung kann nicht kompiliert werden. Der Mediator hat die Fähigkeit, verschiedene Datenquellen anzubinden. Dazu zählen die generischen Typen der mORMot und Spring4D Collections. Aber auch proprietäre Libraries von FastReport, DevExpress usw. werden verwendet. Den Mediator ausschließlich auf freie Bibliotheken umzuschreiben, sprengt den Rahmen eines Artikels. Die besprochenen Auszüge vermitteln aber einen guten Überblick über die grundsätzliche Herangehensweise. Disclaimer: Der Sourcecode ist weder getestet noch optimiert. Die Benutzung der zur Verfügung gestellten Materialien erfolgt auf eigene Gefahr. Vier Schritte ins Glück Grundsätzlich sind nur wenige Schritte notwendig, einen Bericht einzubinden:
Delphi-Quellcode:
Den Weg über die universelle DocVariant Ladefunktion bin ich nur gegangen, um überhaupt ein wenig Sourcecode für die weiteren Erläuterungen zeigen zu können. Die spezialisierten Funktionen erledigen das in einem Aufwasch. Das Gleiche gilt für das direkte Hinzufügen von Objekten, Listen, Arrays und was man sonst noch verarbeiten kann.
var
data: TDocVariantData; begin FReportMediator := TReportMediator.Create(Self); FReportMediator.ReportFileProvider := TReportFileFR3Provider.Create(FReportFileName); // Add DataSet data.InitJsonFromFile(dataSetFileName, JSON_FAST_FLOAT); FReportMediator.AddDocVariantDataSet(GetFileNameWithoutExt(ExtractFileName(dataSetFileName)), Variant(data), []); // Add variables data.InitJsonFromFile(dataVarsFileName, JSON_FAST_FLOAT); FReportMediator.AddDocVariantVariables('ReportVars', data); FReportMediator.ShowReport(0, {IsEditable=} True); Die DocVariant Ladefunktion Auch alle Add*-Funktionen des Mediators realisieren sich aus wenigen Zeilen Sourcecode. Der Grund ist die sehr einfache Methode, wie FastReport Daten rekrutiert. Die Daten werden über eine Event-Funktion zugeführt. Mehr dazu im nächsten Abschnitt. Erst einmal die AddDocVariantDataSet Funktion:
Delphi-Quellcode:
Die Angabe Name wird im Bericht für die Bezeichnung der Datenquelle verwendet. FilterFields bietet die Möglichkeit, unerwünschte Felder der Datenquelle auszublenden.
function TReportMediator.AddDocVariantDataSet(const pmcName: String; const pmcDataVariant: Variant;
const pmcFilterFields: array of RawUtf8): TCustomReportDataSet; var dataSet: TDocVariantReportDataSet; begin dataSet := TDocVariantReportDataSet.Create(FDataSetRoot, pmcName); dataSet.GetFieldNames(pmcDataVariant, pmcFilterFields); dataSet.PrepareData(pmcDataVariant); Result := dataSet; end; Der DocVariant DataSet Um einen eigenen DataSet zu verwenden, gibt es in FastReport die Klasse TfrxUserDataSet. Die Klasse ist minimalistisch. Sie enthält nur wenige Eigenschaften zur Steuerung der Datenzulieferung. Die zwei wichtigsten sind: Fields, was nichts anderes ist als eine Stringliste zur Definition der Feldnamen, und das Ereignis OnGetValue. Der Prototyp ist in der Unit frxClass wie folgt definiert: TfrxGetValueEvent = procedure(const VarName: String; var Value: Variant) of object; Als Alternative gibt es das Ereignis OnNewGetValue, das wie folgt aussieht: TfrxNewGetValueEvent = procedure(Sender: TObject; const VarName: String; var Value: Variant) of object; Die Definition für den DataSet beschränkt sich auf wenige Zeilen:
Delphi-Quellcode:
Die Klasse TCustomReportDataSet ist ein direkter Nachfahre von TfrxUserDataSet. Die Implementation erklärt sich von selbst:
TDocVariantReportDataSet = class(TCustomReportDataSet)
private FDataVariant: TDocVariantData; procedure DoDataGetValue(const pmcName: String; var pmvValue: Variant); public procedure GetFieldNames(const pmcData: Variant; const pmcFilterFields: array of RawUtf8); reintroduce; procedure PrepareData(const pmcData; pmOnOwnGetValue: TReportDataSetGetValueEvent = Nil); override; end;
Delphi-Quellcode:
Wie man sieht, spielt es keine Rolle, ob die Datenquelle vom Typ Objekt oder Array ist. Einschränkend ist, dass nur die erste Ebene unterstützt wird. Zur Erinnerung: DocVariant ist eine beliebig komplexe Datenstruktur aus Objekt(en) und/oder Arrays oder aus Kombinationen von beiden. Die Funktion _Safe stellt sicher, dass es immer einen DocVariant gibt. Notfalls einen leeren Fake DocVariant.
procedure TDocVariantReportDataSet.DoDataGetValue(const pmcName: String; var pmvValue: Variant);
begin case FDataVariant.Kind of dvObject: pmvValue := FDataVariant.Value[pmcName]; dvArray: pmvValue := FDataVariant.Values[RecNo].Value[pmcName]; end; end; procedure TDocVariantReportDataSet.GetFieldNames(const pmcData: Variant; const pmcFilterFields: array of RawUtf8); var i: Integer; run: PDocVariantData; fieldName: RawUtf8; begin Fields.Clear; run := _Safe(pmcData); case run.Kind of dvObject: ; dvArray: run := _Safe(run.Value[0]); else Exit; //=> dvUndefined end; for i := 0 to High(run.Names) do begin fieldName := run.Names[i]; if FindPropName(pmcFilterFields, fieldName) < 0 then Fields.Add(Utf8ToString(fieldName)); end; end; procedure TDocVariantReportDataSet.PrepareData(const pmcData); begin OnGetValue := DoDataGetValue; FDataVariant := _Safe(Variant(pmcData))^; case FDataVariant.Kind of dvObject: RangeEndCount := 1; dvArray: RangeEndCount := FDataVariant.Count; else RangeEndCount := 0; end; RangeBegin := rbFirst; RangeEnd := reCount; First; end; Die Beispiel-Anwendung: kurz und bündig Das Programm ist eine Spielumgebung für mORMot und FastReport. Es stehen fünf Funktionen zur Verfügung: Neues Projekt, Projekt öffnen und schließen, Berichtvorschau oder Berichtdesigner anzeigen. Um gleich loslegen zu können, ist ein Projekt "Test01" fertig erstellt. Grundsätzliches zur Bedienung:
Zusammenfassung Die Möglichkeiten zum Einsatz eines Mediators enden hier nicht. Konsequent setzt es sich bei der Anbindung an die GUI fort. Ob ein Button die Vorschau und/oder den Designer aufruft, warum die Eigenschaft Caption, Image oder ein OnClick Ereignis im Objektinspektor zuweisen. Die Registrierung mit BindButton(btnPrintPreview, TReportMediator.BuildReportID(2008)); reicht aus, egal ob 10x oder 100x in einer Anwendung. Auch der heutige Artikel war vor allem durch die Notwendigkeit zum radikalen Kürzen eine besondere Herausforderung. Bei dieser Aktion besteht immer die Gefahr, dass der rote Faden zum Verständnis verloren geht. Ich hoffe, die Ausführungen blieben nachvollziehbar. mORMot ist gut dokumentiert. Die Hilfe umfasst mehr als 2500 Seiten. Davon enthalten die ersten ca. 650 Seiten einen sehr lesenswerten allgemeinen Teil, der Rest ist API Dokumentation. mORMot muss nicht in der IDE installierten werden! Es reicht aus, die entsprechenden Bibliothekspfade einzufügen. Es stehen viele Beispiele und ein freundliches Forum zur Verfügung. In der mORMot Reihe bisher veröffentlicht:
Thomas Geändert von mytbo (16. Sep 2022 um 14:53 Uhr) Grund: Kopierfehler korrigiert |
Zitat |
Ansicht |
Zur Linear-Darstellung wechseln |
Zur Hybrid-Darstellung wechseln |
Baum-Darstellung |
ForumregelnEs ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.
BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus. Trackbacks are an
Pingbacks are an
Refbacks are aus
|
|
Nützliche Links |
Heutige Beiträge |
Sitemap |
Suchen |
Code-Library |
Wer ist online |
Alle Foren als gelesen markieren |
Gehe zu... |
LinkBack |
LinkBack URL |
About LinkBacks |