CIB merge technischer Leitfaden

10. Anwendungsbeispiele

10.2. Anwendungsbeispiel Serienbrief

Allgemein
Einfacher Mischaufruf über die Kommandozeile
Serienbrief mit 3 Datensätzen als Multi-RTF
Serienbrief mit dynamischer Tabelle und Multi-CSV
Abbrechen des Mischlaufs über Fortschrittsanzeige
Serienbrief mit XML-Datenquelle und Aliasdefinition im RTF
Serienbrief mit XML-Datenquelle, Aliasnamen in XML-Datei, Verwendung von Präfixen
Aufruf eines XML-Jobs über Kommandozeile
Aufruf eines XML-Jobs über Java
Verhalten von NEXT bei fehlenden Variablen festlegen

Allgemein

Soll die Zahlungserinnerung aus vorigem Beispiel nicht nur an einen Kunden verschickt werden, sondern an mehrere, kann dies ohne Änderungen am Anschreiben erfolgen. Nur die CSV-Datei muss um die zusätzlichen Daten der weiteren Kunden ergänzt werden. Die automatische Serienbrieffunktionalität ist am einfachsten so zu verstehen, dass um den Text herum eine gedankliche Schleife existiert, die die Steuerdatei weiterschaltet (implizite Schleife). Im Folgenden wird davon ausgegangen, dass Sie sich im Unterverzeichnis Serienbrief befinden.

Die CSV-Datei Adressen.csv enthält 4 Datensätze:

Vorname;Name;Strasse;PLZ;Ort;Geschlecht;KundenNr;AuftragsNr;Betrag
Max;Müller;Teststr. 3;99999;Testort;M;0987392;232222-4;123118
Franz;Meier;Teststr. 4;12345;Musterdorf;M;9898989;111111-2;999
Maria;Huber;Teststr. 5;54321;Testheim;W;1234567;876564-1;500
Franziska;Bauer;Teststr. 6;77777;Neumusterdorf;W;6665554;981234-0;3333
Franziska;Bauer;Teststr. 6;77777;Neumusterdorf;W;6665554;981234-0;3333


Einfacher Mischaufruf über die Kommandozeile

Folgender einfacher Kommandozeilenaufruf erzeugt den gewünschten Serienbrief (Serienbrief.bat):

cibmrg32.exe ..\Lueckentext\Anschreiben_in.rtf !Serienbrief_out.rtf
Adressen.csv

Das Anschreiben aus dem Lückentext-Beispiel dient als Eingabe, die Ausgabedatei heißt Serienbrief_out.rtf und als Datenquelle wird die erweiterte CSV-Datei mit 4 Datensätzen verwendet. CIB merge erzeugt in diesem Mischlauf automatisch einen Serienbrief, der für jeden Datensatz aus der CSV-Datei eine Zahlungserinnerung (durch Abschnittswechsel voneinander getrennt) enthält. Änderungen bei den Parametern oder im RTF sind nicht notwendig.


Serienbrief mit 3 Datensätzen als Multi-RTF

Es soll nun ein Serienbrief erzeugt werden, der nicht alle Datensätze enthält, sondern nur die ersten drei. Außerdem soll das Ergebnis ein Multi-RTF sein und nicht, wie bisher, ein durch Abschnittswechsel getrenntes RTF. Desweiteren soll die Information geliefert werden, wie viele Dokumente in diesem Mischlauf erzeugt wurden.

Aufgrund der Übersichtlichkeit, wird der Mischlauf wieder über eine Parameterdatei gesteuert, die neben Eingabe-, Ausgabe- und Datendatei die nötigen Parameter enthält, um das gewünschte Ergebnis zu erhalten (Serialletter.bat):

cibmrg32.exe --parameterfile=Serialletter_par.par

Inhalt der Parameterdatei Serialletter_par.par

Fehler sollen protokolliert werden

--logfile=!Serialletter_log.log
Beteiligte Dateien für den Mischlauf
--inputfile=..\Lueckentext\Anschreiben_in.rtf
--outputfile=!Serialletter_out.rtf
--datafile=Adressen.csv
Erzeugung eines Multi-RTF
--serialletter=multi
Ausgabe der Anzahl der erzeugten Dokumente
--statistics=!count.txt
-mDer Mischvorgang verwendet folgende Ein- und Ausgabedateien:
-m@
--merge=3


  • Erläuterungen:

Der Parameter --merge=3 startet den Mischlauf und verwendet alle zuvor gesetzten Parameter. Die Ziffer 3 gibt an, dass ein Serienbrief erzeugt werden soll, in dem die ersten drei Datensätze aus der Datenquelle verwendet werden.

Mit --serialletter=multi wird der Serienbrief als Multi-RTF erzeugt und nicht, wie default-mäßig eingestellt, ein Dokument, welches durch Abschnittswechsel die verschiedenen Datensätze beinhaltet.

Durch den Parameter --statistics wird eine weitere Datei erzeugt, die die Anzahl der generierten Dokumente enthält. In diesem Fall hat die Datei count.txt den Inhalt:

GeneratedDocumentCount=3


Serienbrief mit dynamischer Tabelle und Multi-CSV

Die Zahlungserinnerung soll nun um weitere Informationen ergänzt werden. Für jeden Kunden soll eine Übersicht der offenen Einzelposten auf einer separaten Seite aufgeführt werden.

Die Einzelposten müssen in geeigneter Form zur Verfügung gestellt werden. Am einfachsten erfolgt dies über eine zusätzliche CSV-Datei Einzelposten.csv. Um zu bestimmen, welche Einzelposten zu welchem Kunden gehören, enthält diese CSV-Datei für jeden Einzelposten die zugehörige Auftragsnummer des Kunden. Nach diesen Auftragsnummern sind die Zeilen sortiert (sowohl in der Datei Adressen.csv, als auch in der Datei Einzelposten.csv).

Nun muss angegeben werden, dass für diesen Mischlauf mehrere CSV-Dateien geladen werden sollen. Dies geschieht mit Hilfe einer Multi-CSV-Datei (multi.csv). Sie enthält die Namen aller CSV-Dateien, die im aktuellen Mischlauf geladen werden sollen. Über die Felder in der Kopfzeile der Multi-CSV-Datei, erhält jede CSV-Datei einen Alias zugeordnet, über den dann im Dokument auf diese CSV Dateien zugegriffen werden kann.

Auszug aus Adressen.csv:

Vorname;Name;Strasse;PLZ;Ort;Geschlecht;KundenNr;AuftragsNr;Betrag
Franz;Meier;Teststr. 4;12345;Musterdorf;M;9898989;111111-2;999
Max;Müller;Teststr. 3;99999;Testort;M;0987392;232222-4;123118
…

Auszug aus Einzelposten.csv:

KundeAuftragsNr;Bezeichnung;EinzelBetrag
111111-2;Artikel1;999
232222-4;Artikel1;18
232222-4;Artikel2;123100
…

multi.csv:

Kunden;Einzelposten
Adressen.csv;Einzelposten.csv

Im Anschreiben muss eine dynamische Tabelle eingefügt werden, die die einzelnen Posten auflistet.

Nach dem Text des Anschreibens wird hierfür ein Abschnittswechsel eingefügt. Die neue Seite enthält eine Tabelle mit der Auflistung aller zugehörigen Einzelposten. Dies erfolgt über eine Schleife.

Auszug aus Einzelposten_in.rtf


Der Auftrag {REF AuftragsNr } setzt sich aus folgenden Einzelposten zusammen:

Bezeichnung

Betrag

{ IF { = AND({ MERGEREC ?Einzelposten};{ COMPARE { REF AuftragsNr } = { REF KundeAuftragsNr } })} = 1

“{ REF Bezeichnung }

{REF EinzelBetrag}

{ NEXT Einzelposten }“ \* SOLANGE }

Solange ein Einzelposten vorhanden ist (Prüfung mit { MERGEREC ?Einzelposten}) und die KundeAuftragsNr der AuftragsNr des Kunden entspricht (COMPARE { REF AuftragsNr } = { REF KundeAuftragsNr }), wird die Bezeichnung und der Betrag des Einzelpostens in einer Tabelle ausgegeben und in der Einzelposten.csv zum nächsten Datensatz weitergeschaltet ({ NEXT Einzelposten }). Wären die Daten für den Vergleich rein numerisch, könnte auf das COMPARE verzichtet werden.

Die implizite Schleife bei der automatischen Serienbrieffunktionalität schaltet die Steuerdatei weiter. Wenn nun wie in diesem Fall mehrere Steuerdateien am Mischlauf beteiligt sind, würden alle Steuerdateien weitergeschalten werden. Da die Datei Einzelposten.csv jedoch im RTF selbst mit Hilfe des NEXT-Befehls weitergeschaltet wird, ist dies hier unerwünscht. Um das zu vermeiden wird deshalb eine explizite Schleife um das Anschreiben gesetzt und die Serienbrieffunktion ausgeschaltet.

Auszug aus Einzelposten_in.rtf

{ IF {MERGEREC ?Kunden } = 1“

…Hier folgt das komplette Anschreiben…

{ NEXT Kunden }{ IF {MERGEREC ?Kunden } = 1“… Hier Abschnittswechsel …“}“ \*SOLANGE }

Die Schleife durchläuft alle Kunden aus der Datei Adressen.csv und fügt nach jedem Anschreiben einen Abschnittswechsel ein, wenn es noch einen weiteren Kunden gibt.

Folgender Aufruf erzeugt den gewünschten Serienbrief mit dynamischer Tabelle (Einzelposten.bat):

cibmrg32.exe --parameterfile=Einzelposten_par.par

Fehler sollen protokolliert werden

--logfile=!Einzelposten_log.log
Beteiligte Dateien für den Mischlauf
--inputfile=Einzelposten_in.rtf
--outputfile=!Einzelposten_out.rtf
--datafile=multi.csv
Bei der Datendatei handelt es sich um eine Multi-CSV
--multidatafile
-mDer Mischvorgang verwendet folgende Ein- und Ausgabedateien:
-m@
Serienbrieffunktionalität ausschalten
--merge=1


  • Erläuterungen:

Als Eingabe dient die RTF-Datei Einzelposten_in.rtf. Diese enthält wie beschrieben zwei Schleifen, mit denen die Steuerdateien weitergeschaltet werden.

Der Parameter --multidatafile gibt an, dass es sich bei der Datei, die mit dem Parameter --datafile angegeben wird, um eine Multi-Steuerdatei handelt.

Wie bereits beschrieben, werden die Steuerdateien im RTF selbst weitergeschaltet. Eine Weiterschaltung, die sich durch die automatische Serienbrief-Funktionaltät ergibt, soll unterdrückt werden. Der Parameter --merge=1 führt den Mischlauf als Einzelmischlauf aus. Der Serienbrief wird hier also rein mit Hilfe von RTF-Feldbefehlen erzeugt.


Abbrechen des Mischlaufs über Fortschrittsanzeige

Die RTF-Datei Endlosschleife_in.rtf enthält durch ein vergessenes NEXT-Feld eine Endlosschleife. Unterläuft dem Textprogrammierer ein solcher Fehler, kann der Mischlauf nur über den Task-Manager abgebrochen werden. Um dies zu vermeiden soll im Folgenden ein Fortschrittsdialog angezeigt werden, über den ein Abbruch des Mischlaufs vorgenommen werden kann.

Folgender Aufruf startet den Endlos-Mischlauf mit Fortschrittsanzeige (Endlosschleife.bat):

cibmrg32.exe --parameterfile=Endlosschleife_par.par

Fehler sollen protokolliert werden

--logfile=!Endlosschleife_log.log
Beteiligte Dateien für den Mischlauf
--inputfile=Endlosschleife_in.rtf
--outputfile=!Endlosschleife_out.rtf
--datafile=multi.csv
Bei der Datendatei handelt es sich um eine Multi-CSV
--multidatafile
-mDer Mischvorgang verwendet folgende Ein- und Ausgabedateien:
-m@
Fortschrittsanzeige anzeigen
--dialog=top
Serienbrieffunktionalität ausschalten
--merge=1


  • Erläuterungen:

Als Eingabe dient die RTF-Datei Endlosschleife_in.rtf. Diese produziert beim Mischlauf eine Endlosschleife.

Der Parameter --dialog=top setzt eine Fortschrittsanzeige in den Vordergrund, die auch einen Button zum Abbrechen des Mischlaufs enthält.


Serienbrief mit XML-Datenquelle und Aliasdefinition im RTF

Im Folgenden sollen die Daten nicht als CSV-Dateien übergeben werden, sondern als XML. Die Daten sollen in einer einzigen Datei Daten.xml stehen. Es soll keine Multi-CSV-Datei mehr verwendet werden.

Folgender Auszug aus der Datei Daten.xml zeigt eine mögliche Umsetzung der Daten von CSV nach XML:

<?xml version="1.0"
encoding="ISO-8859-1" ?>
<root>
      <data>
            <Kunden>
                  <Kunde>
                        <Vorname>Franz</Vorname>
                        <Name>Meier</Name>
                        <Strasse>Teststr. 4</Strasse>
                        <PLZ>12345</PLZ>
                        <Ort>Musterdorf</Ort>
                        <Geschlecht>M</Geschlecht>
                        <KundenNr>9898989</KundenNr>
                        <AuftragsNr>111111-2</AuftragsNr>
                        <Betrag>999</Betrag>
                  </Kunde>
                  weitere Kunden ......
            </Kunden>
            <Posten>
                  <Einzelposten>
                        <KundeAuftragsNr>111111-2</KundeAuftragsNr>
                   <Bezeichnung>Artikel1</Bezeichnung>
                     <EinzelBetrag>999</EinzelBetrag>
                  </Einzelposten>
                  weitere Einzelposten....
            </Posten>
      </data>
</root>

Die Aliasdefinitionen werden direkt in der RTF-Eingabedatei NextDef_in.rtf mit Hilfe des Befehls { NEXT ”DEF:Aliasname;<Dateipfad>” } angegeben. Mit dieser besonderen Variante des NEXT Schalters kann im laufenden Dokument einem aktuellen Aliasnamen eine neue Steuerdatei zugewiesen werden. Dieser Befehl lädt gleichzeitig automatisch den ersten Datensatz dieser Datei.

In diesem Fall stehen folgende Aliasdefinitionen im RTF:

{ NEXT ”DEF:Kunden;XML:{ REF XmlDateiname };/root/data/Kunden/Kunde“ }

{ NEXT ”DEF:Einzelposten;XML:{ REF XmlDateiname };/root/data/Posten/Einzelposten“ }

 

Um den Namen der XML-Datei nicht fest im RTF zu verdrahten wird hier stattdessen eine Variable XmlDateiname verwendet. Diese muss von außen über Parameter gesetzt werden. Hinter dem Dateinamen folgt durch Semikolon getrennt die XPath-Angabe zu den jeweiligen Daten. /root/data/Kunden/Kunde liefert alle <Kunde>-Knoten aus der Datei XmlDateiname.

Folgender Aufruf erzeugt den gewünschten Serienbrief mit XML-Datenversorgung (NextDef.bat):

cibmrg32.exe --parameterfile=NextDef_par.par

Fehler sollen protokolliert werden

--logfile=!NextDef_log.log
Beteiligte Dateien für den Mischlauf
--inputfile=NextDef_in.rtf
--outputfile=!NextDef_out.rtf
Setzen des Dateinamens für die XML-Datenversorgung
--set=XmlDateiname=Daten.xml
-mDer Mischvorgang verwendet folgende Ein- und Ausgabedateien:
-m@
Serienbrieffunktionalität ausschalten
--merge=1


  • Erläuterungen:

Als Eingabe dient die RTF-Datei NextDef_in.rtf. Diese enthält auch die Aliasdefinitionen für die XML-Daten.

Der Parameter --set weist der Variablen XmlDateiname den Wert Daten.xml zu. So kann der Dateiname von außen variabel gesetzt werden.

Durch die Aliasdefinitionen im Rohtext ist keine Multi-Steuerdatei mehr erforderlich. Die Parameter --datafile und --multidatafile können daher entfallen.

Da auch hier die Serie durch explizite Schleifen im Rohtext erzeugt wird, wird mit dem Parameter --merge=1 die Serienbrieffunktion ausgeschaltet.


Serienbrief mit XML-Datenquelle, Aliasnamen in XML-Datei, Verwendung von Präfixen

Jetzt sollen die Aliasdefinitionen nicht mehr im Rohtext stehen, sondern zusammen mit den Daten in der XML-Datei. Außerdem soll durch Verwendung von Präfixen im Rohtext die Eindeutigkeit der Variablen gewährleistet werden. Diese Präfixe sollen mit dem Trennzeichen „.“ dem Variablennamen vorangestellt werden.

Um dies zu realisieren, wird die Datei Daten.xml folgendermaßen erweitert. (Daten_mitAlias.xml)

<multi>
 <Kunden>XML:$(this);/root/data/Kunden/Kunde</Kunden>
 <Einzelposten>XML:$(this);/root/data/Posten/Einzelposten</Einzelposten>
</multi>

Das Konstrukt XML:$(this) gibt an, dass sich eine Aliasdefinition auf Daten bezieht, die in der selben XML-Datei stehen, in der sich die Aliasdefinition befindet.

Die Eingabedatei muss so erweitert werden, dass allen Variablennamen der jeweilige Alias gefolgt von einem Punkt vorangestellt wird.

Aus { REF Vorname } wird demnach { REF Kunden.Vorname } usw..

Wird die Variable Betrag z.B. sowohl bei Einzelposten, als auch bei Kunden verwendet, ist durch das Präfix die Eindeutigkeit sichergestellt. Die Parameter können wie immer über eine Parameterdatei definiert werden. Eine Alternative dazu wäre, die Parameter und Daten zusammen in einem sogenannten XML-Job bereitzustellen. Dieser kann ebenfalls über Kommandozeile ausgeführt werden. Ausführungsvarianten über Java und C++ werden im Folgenden ebenfalls erläutert.

Folgender Aufruf erzeugt den gewünschten Serienbrief mit XML-Datenversorgung (Prefix.bat):

cibmrg32.exe --parameterfile=Prefix_par.par

Inhalt der Datei Prefix_par.par:

Fehler sollen protokolliert werden

--logfile=!Prefix_log.log
Beteiligte Dateien für den Mischlauf
--inputfile=Prefix_in.rtf
--outputfile=!Prefix_out.rtf
Pfad zur XML-Datei
--headerfile=XML:Daten_mitAlias.xml
XPath zum Zugriff auf die Aliasdefinitionen
--datafile=/root/multi
--multidatafile
Trennzeichen zwischen Alias und Variablennamen (Punkt ist Default)
--prefix-delimiter
-mDer Mischvorgang verwendet folgende Ein- und Ausgabedateien:
-m@
Serienbrieffunktionalität ausschalten
--merge=1


  • Erläuterungen:

Als Eingabe dient die RTF-Datei Prefix_in.rtf, welche wie beschrieben um Aliasnamen bei den Variablen erweitert wurde.

Der Parameter --headerfile gibt die zu verwendende Datenquelle (Daten_mitAlias.xml) an und der Parameter --datafile den XPath zu den Aliasnamen.

Durch Hinzufügen des Aufrufparameters --multidatafile, interpretiert CIB merge dann die Aliasdefinitionen selbständig und stellt die zugehörigen Aliasnamen bereit.

Dadurch können die {next}-DEF-Feldanweisungen im Rohtext entfallen.

Der Parameter --prefix-delimiter definiert den Punkt als Trennzeichen zwischen Alias und Variablennamen. Der Rohtext muss so erweitert werden, dass allen Variablen der entsprechende Alias gefolgt von diesem Trennzeichen vorangestellt wird.

Das Ergebnis wird in die Datei Prefix_out.rtf geschrieben.


Aufruf eines XML-Jobs über Kommandozeile

Liegen die Daten ohnehin als XML vor, ist es möglich, die Parameter ebenfalls in einem XML zu setzen. So lassen sich die Daten und die Parameter in einer einzigen XML-Datei unterbringen. In einem sogenannten merge-Step werden alle notwendigen Properties gesetzt. Diese Job-XML (PrefixJob.xml) kann dann folgendermaßen über die Kommandozeile aufgerufen werden (PrefixJob.bat):

cibrsh.exe -d PrefixJob.xml

Auszug aus der Datei PrefixJob.xml (Kommentare beginnen mit <!-- und enden mit -->)

<step name="merge" command="merge">
<!-- Liste der Properties für diesen Step -->
<properties>
      <!-- Daten werden in diesem XML mitgegeben -->
      <property name="--logfile">!PrefixJob_log.log</property>
      <property name="--inputfile">Prefix_in.rtf</property>
      <property name="--outputfile">!Prefix_out.rtf</property>
      <property name="-h">XML:$(inline)</property>
      <property name="--datafile">/root/multi</property>
      <property name="--multidatafile"/>
      <property name="--prefix-delimiter"/>
      <property name="-@">1</property </properties> </step>
     

Die Daten, die zuvor über die Datei Daten_mitAlias.xml bereitgestellt wurden, können direkt mit in der PrefixJob.xml übergeben werden. Dies wird mit XML:$(inline) beim Parameter -h angegeben. Hier muss explizit die Kurzschreibweise -h verwendet werden, da diese genau so erwartet wird. Das gleiche gilt für -@.

Die Daten aus Daten_mitAlias.xml können dann direkt in die PrefixJob.xml übernommen werden, indem sie direkt unterhalb des <root>-Knotens eingefügt werden.


Aufruf eines XML-Jobs über Java

Wird ein XML-Job verwendet, kann dieser auch über Java ausgeführt werden. Hierfür wird die Klasse JCibJobJob verwendet. In folgendem kleinen Java-Programm wird ebenfalls die Datei PrefixJob.xml ausgeführt:

Auszug aus MergeJob.java:


JCibJobJob t_Job = new JCibJobJob();
t_Job.initialize();
if (!t_Job.isInitialized())
{
            // Fehler beim Initialisieren
            System.err.println("Fehler beim Initialisieren");
            System.exit(1);
}
try
{
 t_Job.setProperty(ICibJobJob.PROPERTY_INPUTFILENAME,
"PrefixJob.xml");
            //Job ausführen
            t_Job.execute();
            //Fehlerbehandlung
            int t_Error = ((Integer)t_Job.getProperty(IComodJob.PROPERTY_ERROR)).intValue();
            if (t_Error != 0)
            {
            // Fehler beim Ausführen des Jobs
            String t_Errortext =
(String)t_Job.getProperty(IComodJob.PROPERTY_ERRORTEXT);
            System.err.println("Fehler beim Ausführen: "+t_Error+" "+t_Errortext);
            }
}
finally
{
            t_Job.terminate();
}
…

Im Folgenden fehlt in einem Datensatz ein XML-Knoten. Die Datei Daten.xml wird so angepasst, dass im dritten Kunden-Datensatz der Knoten <KundenNr> fehlt (Daten_NextMode.xml). Im Ergebnis würde an der Stelle, an der diese Variable eingesetzt wird, einfach nichts stehen. Im Folgenden soll eine Variable, die in einem Datensatz enthalten ist, im nächsten jedoch nicht mehr, gelöscht werden. Dies soll zu einem Fehler führen und der Mischvorgang soll abgebrochen werden.

Folgender Aufruf erzeugt das gewünschte Verhalten (NextMode.bat):

cibmrg32.exe --parameterfile=NextMode_par.par

Inhalt der Datei NextMode_par.par:

Fehler sollen protokolliert werden

--logfile=!NextMode_log.log
Beteiligte Dateien für den Mischlauf
--inputfile=NextDef_in.rtf
--outputfile=!NextMode_out.rtf
Setzen des Dateinamens für die XML-Datenversorgung
--set=XmlDateiname=Daten_NextMode.xml
-mDer Mischvorgang verwendet folgende Ein- und Ausgabedateien:
-m@
Verhalten für Next festlegen, wenn Variable nicht vorhanden
--next-mode=delete
Serienbrieffunktionalität ausschalten
--merge=1


  • Erläuterungen:

Der Parameter --next-mode bewirkt mit der Belegung „delete“, dass die fehlende Variable KundenNr gelöscht wird und somit nicht mehr definiert ist. Es kommt zu einem Fehler

unbekannte Variable:
Name: KundenNr

und der Mischvorgang wird abgebrochen.