Reporting mit dBASE
Alternativen zum internen Reportgenerator
von Lutz Conrad

NACH Datenerfassung und Bearbeitung im PC möchte man die Daten zu Papier bringen und per Fax oder EMail versenden. Hierzu stellt dBASE eine eigene Reportengine als Two-Way-Tool zur Verfügung. Abgesehen davon, daß man tatsächlich fast jeden Report damit programmieren kann, stehen Aufwand und Ergebnis in keinerlei Verhältnis. Der Designer ist schlicht nur dazu zu verwenden, einen groben Entwurf des Reports herzustellen.

Die wesentlichsten Nachteile aus meiner Sicht sind:

- ein exaktes Positionieren von Controls mittels Designer ist nicht möglich, beim Hinzufügen von Controls werden die bisher angeordneten oft in ihrer Position verändert, eine Feinpositionierung ist somit nur im Quelltexteditor möglich
- die mittels output einstellbaren Ausgabemedien ermöglichen keinen direkten Export in Fremdformate, z.B. PDF, RTF
- es wird kein Abbild des fertigen Reports erzeugt, daher wird bei jedem Seitenwechsel das Rendering erneut durchgeführt; was neben einer deutlichen Verringerung der Performance dazu beiträgt, daß der gedruckte Report oft ganz anders aussieht als die Vorschau (Seitenzahlen, Summen usw.)
- das Senden von Reports per EMail ist nur über zusätzliche Software möglich
- das Report-Viewer-Control bietet keine Möglichkeit der Skalierung
- es gibt keine integrierte Möglichkeit zum Erstellen von Chart-Objekten

Auf der dBKON 2002 wurde Combit List&Label 8 vorgestellt. Bei aller anfänglichen Skepsis habe ich einige interessante Alternativen zum dBASE-Reportgenerator gesehen. Insbesondere hatte ich Bedenken, ob sich eine datenbankunabhängige Software wirklich so einfach in dBASE einbinden ließe. Den Entschluß, den Umstieg zu versuchen, habe ich zu keiner Zeit bereut. Innerhalb kürzester Zeit wurden die bisherigen Reports meiner Anwendungen auf List&Label angepaßt. Neuentwicklungen erfolgen nur noch mittels List&Label.

Entscheidend für meinen Wechsel waren folgende Aspekte:

- der Designer ist benutzerfreundlich gestaltet und sehr stabil
- es können Summen- und Benutzervariablen sowie benutzerdefinierte Formeln verwendet werden
- die Vorschau des erzeugten Reports entspricht exakt dem späteren Ausdruck
- bei der Vorschau kann schnell zwischen einzelnen Seiten umgeschaltet werden, es ist ohne Verzögerung möglich, von der 1 auf die letzte Seite und zurück zu wechseln, besonders bei umfangreichen Listen ist dies von großem Vorteil
- listen-, benutzer- und computerabhängige Speicherung der Druckereinstellungen sind möglich
- formatierte Textobjekte (wie z.B. in Word) werden direkt unterstützt
- vielfältige Exportmöglichkeiten ohne zusätzliche Software und Lizenzgebühren (*.PDF, *.RTF, *.XLS)
- direkter Versand der erstellten Listen per Mail/Fax ist möglich
- Listen können durch den Kunden individuell angepaßt werden (Professional Version)

Aber ganz ohne Programmieraufwand geht es nicht! Es muß eine Schnittstelle zwischen dBASE und List&Label definiert werden, über die folgende Vermittlung realisiert wird:

- Definition des Zugriffs auf die List&Label API
- Anmeldung der Datensatzobjekte bei List&Label
- Namentliche Definition der Felder, Variablen und Parameter
- Regelung der Datenversorgung der List&Label Engine
- Konvertierung der HTML-Tags von Memo-Feldern

Hierzu wurde die benutzerdefinierte Klasse `LLReport.CRP` angelegt. Die Dateierweiterung ist hier nur aus Kompatibilitätsgründen gewählt, die Klasse selbst ist nicht von Report, sondern von Object abgeleitet. Im Objektinspektor wird unter `baseClassName` der Eintrag LLReport angezeigt.

Die Klasse LLReport

Die Klasse LLReport bildet die Schnittstelle von dBASE zu combit List&Label.

Syntax:

| `[<oRef>] = new LLReport()`
| ``

oRef

Eine Variable oder Eigenschaft, in der eine Referenz auf ein neu erstelltes Report-Objekt gespeichert wird.

Die Klasse LLReport verfügt über folgende Eigenschaften und Methoden:

Eigenschaften

Eigenschaft | Standard | Verwendung/Hinweise
baseClassName | LLReport |
directory | SET("DIRECTORY") | Verzeichnis, das beim Aufruf des Reports aktiv ist
LL | Objekt | List&Label Objekt
LL.Application | Name der EXE | Ist eine Variable _app.oInfo.ListAndLabel vom Typ "C" definiert, wird diese als Standard verwendet
LL.AutoFaxVar | "" | Name des Feldes bzw. der Variablen mit Faxnummer des Empfängers
LL.AutoMailVar | "" | Name des Feldes bzw. der Variablen mit Email-Adresse des Empfängers
LL.CanSelFont | false | Flag, ob Schriftartauswahl für RTF-Objekte in Etiketten
LL.CanShowPreview | true | Flag, ob Vorschau (wenn gewählt) sofort angezeigt wird
LL.ChartMode | 0 | 0 Standard, 1 erweitert (Spalten), 2 erweitert (Objekte)
LL.Chartfields | ARRAY | Chartfelder für erweiterten Modus (derzeit nicht funktional, es wird nur der Standardmodus unterstützt)
LL.ChooseDest | true | Flag, ob Zielauswahl möglich
LL.Copies | 0 | Anzahl der Kopien, 0 mit Auswahl
LL.CopyCountField | "" | Name des Feldes, mit dem die Anzahl der zu druckenden Etiketten festgelegt wird
LL.CopyCountValue | 1 | Standardvorgabe, falls CopyCountField leer oder nicht vorhanden
LL.DataObjects | NULL | Objectarray mit weiteren Datenzugriffsobjekten (rowsets)
LL.Debug | false | Debugmodus
LL.DefDir | "" | Verzeichnis mit List&Label Definitionen (Vorlagen)1
LL.DeletePreview | true | Temporäre Vorschaudateien nach Ausgabe löschen
LL.Design | false | Flag für Designermodus
LL.Destination | 3 | Ausgabeziel, dBASE-Äquivalent (Vorschau)
LL.Destinations | "" | Mögliche Ausgabeziele, Leerstring für alle
LL.EMail | "" | EMail-Empfänger
LL.EMailBCC | "" | EMail-ZusatzEmpfänger
LL.EMailBody | "Dies ist der gewünschte Report" | EMail-Text
LL.EMailCC | false | EMail-Zusatzempfänger
LL.EmailSubjectl | 0 | EMail-Betreff
LL.Error | 0 | Fehlernummer
LL.Extension | ".LST" | Unterstützt werden: Listenprojekte: ".LST"," Karteikartenprojekte ".CRD",".BRF","PLN" Etikettenprojekte ".LBL",".ETI",".BAR"
LL.ExportDir | "" | Hauptverzeichnis für Exportdateien2
LL.ExportFilename | "Export" | Vorgabename für Exportdatei
LL.Fax | "" | Faxnummer des Empfängers
LL.FileCanAdd | false | Flag zum Hinzufügen von Dateien
LL.FileCanSelect | false | Flag zum Auswählen von Dateien
LL.Filemask | "" | Maske für Dateinamen bei Auswahlmöglichkeit
LL.Filename | "" | Name der List&Label Vorlage
LL.Firstpage | 0 | Startseite, 0 mit Auswahl
LL.IntCopies | 1 | Anzahl der Etiketten mit gleichen Daten (nur für Etikettenprojekte)
LL.LizenzInfo | "" | Lizenzschlüssel (Diese Variable muß vom Anwender gesetzt werden!)
LL.MemoFieldsAsRTF | true | Memofelder in RTF-Objekten abbilden
LL.NoDialogs | false | Keine Benutzeraktion, nur Standards oder Vorgaben verwenden
LL.ObjInput | ARRAY | für Erweiterung vorgesehen, derzeit nicht funktional
LL.PageCount | 0 | Wenn beim Start des Reports =-1, erfolgt eine Ermittlung der Seitenanzahl . Diese steht dann in der Variablen C_PageCount zur Verfügung. Nur für Listenprojekte mit Seite X von Y.
LL.Params | ARRAY | Array mit benutzerdefinierten Konstanten (L&L Variablen)
LL.Params[1] | ARRAY | {"Lizenznummer",<Lizenznummer>} Ist die Variable _app.oLizenz.Lizenz vom Typ "C", wird diese für <Lizenznummer> verwendet, andernfalls der Text "**** Diese Software ist nicht lizenziert ****"
LL.Params[2] | ARRAY | {"Lizenznehmer",<Lizenznehmer>} Ist die Variable _app.oLizenz.Lizenznehmer vom Typ "C", wird diese für <Lizenznehmer> verwendet, andernfalls der Text "Testversion "
LL.Params[3] | ARRAY | {"Zielfaxnummer",""}
LL.PDFEncrypt | "0" | #"0" -> PDF-Datei wird verschlüsselt
LL.PDFEncryptCopy | "0" | #"0" -> Inhalte der PDF-Datei können in die Zwischenablage kopiert werden3
LL.PDFEncryptEdit | "0" | #"0" -> Inhalte der PDF-Datei können bearbeitet werden3
LL.PDFEncryptLevel | "0" | Verschlüsselungstiefe ("0" 40 bit, sonst 128 bit)3
LL.PDFEncryptPrint | "1" | #"0" -> PDF-Datei kann gedruckt werden3
LL.PDFFontMode | "5" | Schriftarteneinbindung in PDF-Dokumente (s.a. L&L-Doku)
LL.PreviewDir | "" | Verzeichnis für Vorschaudaten2
LL.PrintersDir | "" | Verzeichnis mit Druckerdefinitionen2
LL.Projektart | LL_PROJEKT_LIST | wird automatisch in Abhängigkeit vom Projekt gesetzt
LL.RealTime | false | Zeitangaben immer aktualisieren
LL.ResetList | false | Seitenzählung zurücksetzen (nur Listenprojekte)
LL.ResetPage | true | Seitenzählung zurücksetzen (nur Karteikartenprojekte)
LL.ResetUser | false | Variable (Konstanten) nach jedem Datensatz neu lesen
LL.SerienEmail | false | für Erweiterung vorgesehen, derzeit nicht funktional
LL.SerienFax | false | für Erweiterung vorgesehen, derzeit nicht funktional
LL.SetOffset | false | Dialog zur Feinpositionierung anzeigen
LL.ShowEmailDialog | true | Dialog zum EMail-Versand anzeigen
LL.SortVariables | false | Variable im Designer alphabetisch sortieren
LL.Special | "" | Zusatzverzeichnis mit benutzerdefinierten Anpassungen einzelner Reports
LL.SuppPageBreak | true | Seitenumbruch in Text-Objekten unterstützen
LL.Tablenames | false | Feldnamen mit Tabellennamen anzeigen
LL.UserBreak | false | Flag, ob durch Benutzer abgebrochen
LL.Version |  | interne LL-Versionsnummer
LL.VarsAndFields | false | Flag, ob bei Listenprojekten neben Feldern auch Variablen im Funktionsdialog des Designers angezeigt werden sollen
LL.Zoomfaktor | 100 | Zoomfaktor beim Öffnen der Vorschau
output | 3 | Ausgabeziel
ParentWindow | 0 | Fensterhandle des aufrufenden Fensters, falls nicht verfügbar, wird _app.frameWin.hWnd verwendet
scaleFontBold | false | Standardauszeichnung für RTF-Text
scaleFontName | "Arial" | Standardfont für RTF-Text
scaleFontSize | 10 | Standardschriftgrad für RTF-Text
streamsource1 | OBJECT | Hauptdatensatzbereich (Query oder Array4)
Tools | OBJECT | Interne Funktionsbibliothek

Methoden

| Init() | Definition der Standards, diese Methode muß aus dem Report mittels SUPER::Init() nach der Definition der Datensatzbereiche (des Hauptdatensatzbereichs) aber vor allen weiteren Zuweisungen aufgerufen werden. Rückgabewert: keiner
| render() | Startet den Report Rückgabewert: bei Fehler oder Abbruch false, sonst true

Alle weiteren Methoden dienen der internen Verarbeitung und sollten daher durch den Programmierer nicht direkt aufgerufen werden.

Anmerkungen

1. Wird der Pfad zur Hauptdatenbank der Anwendung in`_app.DatabasePath` gespeichert, so werden die Reportvorlagen standardmäßig im Verzeichnis`<Datenbankverzeichnis>\LLDef` gesucht.

   Ist mit `LL.Special` ein Unterverzeichnis mit speziellen Anpassungen referenziert, so wird zunächst in diesem Verzeichnis gesucht, ist der Report dort nicht vorhanden, wird die Vorlage aus dem o.g. Verzeichnis verwendet.

   Ist`_app.DatabasePath` nicht definiert, so wird der Report im Anwendungsverzeichnis gesucht.

2. Das Basisverzeichnis wird durch eine Variable`_app.oUser.UserDir` vom Typ `C` oder durch das Verzeichnis der EXE definiert. Ausgehend von diesem Verzeichnis wird, falls nicht explizit anders angegeben, folgende Struktur angelegt:

   | <Benutzerverzeichnis>\<Anwendung>\Printers | benutzerspezifische Druckerdefinitionen
   | <Benutzerverzeichnis>\<Anwendung>\Previews | Vorschauverzeichnis
   | <Benutzerverzeichnis>\<Anwendung>\Exports | Exportierte Listen, je Format ein Unterverzeichnis

3. Nur wirksam, wenn `LL.PDFEncrypt # "0"`

4. Wird als Datenquelle ein Array verwendet, ist folgender Code in die `Init()` Methode der Reportklasse aufzunehmen:

   | `this.Streamsource1.rowset = new OBJECT()` `this.Streamsource1.rowset.handle=-1` `this.Streamsource1.rowset.fields=new ARRAY()` `this.Streamsource1.rowset.fields.add({<Spaltenname 1>, …, <Spaltenname n>})` `this.Streamsource1.rowset.fields.add({<Typ 1>, …, <Typ n>})` `this.Streamsource1.rowset.fields.add({<Länge 1>, …, <Länge n>})` `this.Streamsource1.rowset.fields.add({<Dezimalstellen 1>, …, <Dezimalstellen n>})` `this.Streamsource1.rowset.fields.add({<Inhalt Zeile 1 Spalte1, …, <Inhalt Zeile1, Spalte n})` `.....` `this.Streamsource1.rowset.fields.add({<Inhalt Zeile m Spalte1, …, <Inhalt Zeile m, Spalte n})`
   | ``

   Die Schnittstelle ruft bei jeder Navigation im Array eine Methode `SelectData()` auf. Diese kann bei Bedarf überschrieben werden, um so eine Navigation in verbundenen Datensatzbereichen zu erzwingen.

Datentypzuordnungen

Die Vermittlung der in Tabellen enthaltenen Datenfelder erfolgt ohne weiteren Programmieraufwand. Dabei realisiert die Schnittstelle folgende automatische Datentypzuordnungen:

dBASE | List&Label
Character | Character
Logical | Logical
Memo | RTF[|<nSize>][|cFontname] Als Standardschrift wird die mittels scaleFontName, scaleFontSize und scaleFontBold zugewiesene Schriftart verwendet. HTML-Tags werden bei der Konvertierung berücksichtigt.
Numeric,AutoInc,Float, Long, Double | Numeric
Date | Date
Timestamp | Character (es wird DTTOC() verwendet)
OLE, Binary | keine Vermittlung

Bei der Konvertierung von HTML.formatiertem Text in das RTF-Format besteht zusätzlich die Möglichkeit, mit dem Tag <pagebreak> bzw <umbruch> einen sofortigen Seitenumbruch zu erzwingen.

Kalkulationsfelder können wie gewohnt bei der Definition der Datensatzbereiche angelegt werden. Zusätzlich besteht jedoch die Möglichkeit, diese in einem Array an den Hauptdatensatzbereich anzufügen. In letzterem Falle muß im `Init()` folgende Syntax verwendet werden:

| `this.streamsource1.rowset.calcFields=new ARRAY()` `this.streamsource1.rowset.calcfields.add({<Wert>,<Name>,<Typ>,<Länge>,<Dezimalstellen>})`
| ``

Konstanten müssen an List&Label über das Array LL.Params vermittelt werden. Dieses Array enthält je zu übermittelnden Wert ein Sub-Array mit folgendem Aufbau:

| `{<Name>,<Wert>[,<Typ>[,<Länge>[,Dezimalstellen]]]}`
| ``

Als Typ sind die o.g. dBASE-Spezifikationen zu verwenden. Zusätzlich können die Typen `GRAPHIC` und `RTF[|nSize][|cName]` verwendet werden. Beide Formate erwarten als Wert eine Zeichenkette. Beim Format `GRAPHIC` ist dies ein Verweis auf eine Bilddatei. Ist der Typ nicht angegeben, wird automatisch `CHARACTER` vorausgesetzt, Länge und Dezimalstellen werden bei Bedarf anhand des Datentyps zugeordnet.

Verwendung

Der Aufruf aus einem Programm erfolgt stets über:

| `LOCAL r` `SET PROCEDURE TO <Reportdatei> ADDITIVE` `r = new <Reportklasse>` `r.Init(([<Parameter 1>[, …Parameter n]])` `r.render()`
| ``

Es wird empfohlen, für jede Anwendung eine zwischengeschaltete Report-Basisklasse zu verwenden und die einzelnen Reports nicht direkt von LLReport sondern von dieser Klasse abzuleiten.

Beispiel:

| `CLASS AppReport OF LLReport FROM LLReport.CRO CUSTOM` `FUNCTION Init(lDirekt,lDesign)` `SUPER::Init()` `IF NOT EMPTY(lDirekt)` `this.output = 1 //Direktdruck ohne Vorschau` `ENDIF` `IF NOT EMPTY(lDesign)` `this.LL.Design = true //Report im Designmodus aufrufen` `ENDIF` `this.LL.Lizenzinfo = <Persönlicher Lizenzschlüssel, den Sie von combit erhalten>` `RETURN` `ENDCLASS`
| ``

Die Reportklasse selbst hat dann folgenden grundsätzlichen Aufbau

| `CLASS SampleReport OF AppReport FROM AppReport.CRP` `[<Definiere Datenzugriffsobjekte>]` `Function Init([<Parameter 1>[, …Parameter n]],lDirekt,lDesign)` `[<Definiere Besonderheiten der Datenzugriffsobjekte in Abhängigkeit von Parametern (Index, Filter...)>]` `SUPER::Init(lDirekt,lDesign)` `this.LL.Filename = <Reportname>` `// Weitere Konstanten definieren, falls erforderlich` `this.LL.Params.add({<Name 1>,<Wert>[,<Typ>[,<Länge>[,Dezimalstellen]]]})` `...` `this.LL.Params.add({<Name n>,<Wert>[,<Typ>[,<Länge>[,Dezimalstellen]]]})` `// Weitere Datensatzbereiche anmelden, falls erforderlich` `this.LL.DataObjects.add(<Weiterer Datensatzbereich 1>)` `...` `this.LL.DataObjects.add(<Weiterer Datensatzbereich n>)` `// Kalkulationsfelder definieren, falls erforderlich` `this.streamsource1.rowset.CalcFields=new ARRAY()` `this.streamsource1.rowset.CalcFields.add({<Wert>,<Name 1>,<Typ>,<Länge>,<Dezimalstellen>}` `...` `this.streamsource1.rowset.CalcFields.add({<Wert>,<Name n>,<Typ>,<Länge>,<Dezimalstellen>}` `// Setzen weiterer LL-Properties` `retuen` `Function Sourcefile_onNavigate` `/*` `Wird nur benötigt, wenn mit CalcFields-Array gearbeitet wird. In diesem Falle werden hier die Werte des Arrays gesetzt. Dies ist z.B. dann von Vorteil, wenn Berechnungen in externen Modulen durchgeführt werden sollen, um das Ergebnis in den Report zu übernehmen, z.B..` `this.Calcfields[1][1]=_app.Tools.GetTagesart((this.fields["Datum"].value))` `*/` `return` `ENDCLASS`
| ``

Tip: Obwohl die in der Datei `LLReport.CRO` enthaltene Klasse nicht von der dBASE Stock-Class Report abgeleitet ist, wird im Dateinamen die Erweiterung CRO verwendet. Damit wird eine entsprechende Zuordnung im Projektexplorer erreicht. Es wird empfohlen, diese Verfahrensweise beizubehalten, also benutzerdefinierte Reportdateien mit der Endung`*.CRP` und die in der untersten Hierarchieebene befindlichen Reports mit der Endung`*.REP` zu versehen.

Verwendung der Beispiele

Zur Verwendung der Beispiele wird ein BDE-Alias namens LLSample benötigt. Dieser wird beim ersten Aufruf des Beispiels automatisch angelegt und verweist auf das Verzeichnis DATA der Beispielstruktur.

Zwischen die eigentlichen Reports und die Basisklasse LLReport wird ein benutzerdefinierter Report geschoben, in dem allgemeingültige Vorgaben für alle Reports des Projekts definiert werden. Hier erfolgt die Zuweisung des combit-Lizenzschlüssels. Weitere Festlegungen dienen zur Gewährleistung eines einheitlichen Erscheinungsbildes aller Reports des Projekts. U.a. werden definiert:

- Farben für Zebramuster, Kopf und Fußzeilen
- Anwendungslogo
- Briefkopf des Lizenznehmers (Nutzers der Anwendung)

Die Beispielanwendung selbst besteht aus dem Formular `Beispiele.WFM` und den von dort aufgerufenen Reports. Alle Dateien (außer LLReport) liegen im Quelltext vor und können als Muster für eigene Entwicklungen verwendet werden.

Für eine Trial-Version können Sie einen beliebigen Lizenzschlüssel verwenden.

Im Auswahldialog finden Sie den Aufruf für folgende Programmbeispiele:

Für alle Reports wurden sämtliche verfügbaren Exportmodule bereitgestellt. Beim Anklicken der Schaltfläche Report mit der linken Maustaste wird ein Auswahldialog für das Ausgabeziel geöffnet. Beim Klick auf die Schaltfläche Report mit der rechten Maustaste wird der Report sofort zum Drucker gesandt.

Wird mit der rechten Maustaste bei gleichzeitig gedrückter STRG-Taste geklickt, öffnet sich der List & Label-Designer (vorausgesetzt List&Label ist in Vollversion installiert oder auf dem Rechner befindet sich die List&Label-Professional-Runtime).

In diesem Dialog legen Sie das Ausgabeziel für den Report fest.

Artikelliste (Beispiel von combit)

Bei Etikettenprojekten haben Sie neben der Auswahl des Ausgabeziels außerdem die Möglichkeit festzulegen, bei welcher Position mit dem Etikettendruck begonnen wird. Somit können auch bereits verwendete Druckvorlagen vollständig genutzt werden.

Etiketten (Beispiel von combit)

Adreßliste

Nach Auswahl der gewünschten Option wird die komplette Liste gedruckt. Im Report wird hier nur eine Tabelle genutzt.

Geburtstagsliste mit Beschränkung auf einen Zeitraum.

Karteikarte

Für die im Tabellenobjekt ausgewählten Datensätze werden Karteikarten gedruckt, eine Mehrfachauswahl ist möglich. Das Umschalten der Sortierfolge im Tabellenobjekt erfolgt durch Doppelklick auf den Spaltenkopf. Rote Farbe weist auf die aktuelle Sortierung hin, grüne Farbe auf eine mögliche Sortierung.

Als Projektart wird ein Karteikartenprojekt verwendet. Die Datenbindung erfolgt auch in diesem Beispiel über eine einzelne Tabelle.

Karteikarten für die ausgewählten Personen

Brief

Nach Eingabe eines Brieftextes wird ein Serienbrief für alle Adressen erstellt. Die Faxnummer wird direkt übergeben, so daß auch ein Serienfax möglich ist (Tobit-Faxware-Client).

Serienbrief

Rechnung

Im oberen Tabellenobjekt sind die Rechnungen aufgeführt, im unteren die dazugehörigen Rechnungspositionen, die entsprechend Navigation aktualisiert werden. Zum Ausdruck der Rechnungen können auch hier mehrere Datensätze markiert werden.

Im Report werden hier mehrere Datensatzbereiche verwendet. Die Haupttabelle enthält die Rechnungsangaben, die Rechnungspositionen kommen aus einer Detailtabelle. Adreßangaben werden bei der Navigation in der Haupttabelle verknüpft.

Gescanntes Formular

In diesem Beispiel wird davon ausgegangen, dass der Ausdruck im Zusammenhang mit einem eingescannten Formular ausgeführt wird.
Wenn direkt in ein vorhandenes (vorgedrucktes) Formular gedruckt werden soll, kann abhängig von den Druckerparametern eine Feinjustierung des Reports erforderlich werden. Verwenden Sie hierzu die entsprechende Option, die eine Positionierung auf 0,01 mm ermöglicht.

Diagramme

Das Beispiel Adressen nach Orten vermittelt anhand eines Tortendiagramms die Verteilung der Kunden auf Wohnorte.

Mit dem Beispiel Umsatz nach Region werden die Umsätze hinsichtlich Region und Rechnungsmonat in einem 3-D Balkendiagramm dargestellt.

Am Beispiel Umsatz nach Monat wird in einem Liniendiagramm der Verlauf der Umsatzentwicklung aufgezeigt. Für jede Region wird hierfür eine andersfarbige Linie verwendet.

Um die beigefügten Beispiele herunterzuladen, bitte hier klicken (283 Kb als Zip-Datei). |