#limit (11.0)##pagelength (16.5)##block# #start (2.0,0.0)# #page (133)# #headodd# #center#EUDAS#right#% #end# #headeven# %#center#EUDAS #end# #center#1 13 Programmierung von Druckmustern 13.1 Abkürzungen In den vorigen Kapiteln haben Sie erfahren, daß man Feldmuster von ganz bestimmter Länge definieren kann, deren Inhalt in genau dieser Länge eingesetzt und bei Bedarf abgeschnitten wird. Bei der Angabe dieser Länge spielt jedoch die Länge des Feldnamens eine ganz entscheidende Rolle. Das kürzeste Feldmuster fester Länge, das Sie definieren können, ist nämlich zwei Zeichen länger als der Feld­ name (ein Musterzeichen vorher und eins nachher). Hätte das Feld 'PLZ' den Namen 'Postleitzahl' bekommen, so müßte ein solches Feldmuster mindestens eine Länge von 14 Zeichen haben. Damit Sie mit diesem Feldnamen auch ein Feldmuster der Länge 4 bekommen können (Postleitzahlen haben in den seltensten Fällen mehr als 4 Stellen), haben Sie die Möglichkeit, den Namen 'Postleitzahl' für die Verwendung im Druckmuster geeignet abzu­ kürzen. Abkürzungen haben jedoch noch eine viel weitreichendere Bedeutung. Mit ihnen ist es möglich, nicht nur die Feldinhalte einer EUDAS-Datei einzusetzen, sondern auch jeden anderen Text, den Sie mit einem ELAN-Programm erzeugen können. Die einfachsten zusätzlichen Daten, die Sie verwenden können, sind z.B. Datum und Uhrzeit. Für weitergehende Zwecke können Sie die Inhalte der EUDAS-Datei auch für Berechnungen verwenden und damit so umfangreiche Probleme wie das Schreiben von Rechnungen oder statistische Auswertungen unter Verwendung eines Druck­ musters lösen. #on("b")#Abkürzungsteil#off("b")# Abkürzungen werden in einem speziellen Abkür­ zungsteil am Ende eines Abschnittes angegeben. Der Abkürzungsteil wird durch die Anweisung % ABKUERZUNGEN eingeleitet. Eine Abkürzungsdefinition hat eine ähnliche Form wie ein Refinement (Falls Sie nicht wissen, was das ist, vergessen Sie es). Zu Beginn steht der Name der Abkürzung in Form eines Feld­ musters, beginnend in der ersten Spalte. Danach folgt, durch Leer­ zeichen getrennt, ein Doppelpunkt in der gleichen Zeile. Daran schließt sich ein beliebiger ELAN-Ausdruck an, der sich in freiem Format über beliebig viele Zeilen erstrecken kann und mit einem Punkt abgeschlossen werden muß. Dieser ELAN-Ausdruck muß ein TEXT-Objekt liefern. #on("b")#Feldinhalt#off("b")# Für die Abfrage von Inhalten aus einer EUDAS-Datei ist der Ausdruck f ("Feldname") vordefiniert. Die Abkürzung des Feldes 'Postleitzahl' würde also als Ausschnitt folgendermaßen aussehen: % ABKUERZUNGEN &p : f ("Postleitzahl") . Mit dieser Definition kann man im Muster so verfahren, als ob das Feld 'Postleitzahl' auch 'p' hieße. Diese einfachste Form der Ab­ kürzung können Sie natürlich variieren, indem Sie für 'p' und 'Postleitzahl' Ihre eigenen Namen einsetzen. #on("b")#Übersetzung#off("b")# Beachten Sie, daß das Druckmuster in ein ELAN-Pro­ gramm umgeformt werden muß, da ELAN-Ausdrücke in ihm vorkom­ men. Das automatisch erzeugte ELAN-Programm wird dann vom ELAN-Compiler übersetzt und ausgeführt. Fehler in den ELAN-Aus­ drücken im Abkürzungsteil können erst vom ELAN-Compiler ent­ deckt werden. Dieser kennt jedoch das Druckmuster nicht und mel­ det die Fehler anhand des generierten Programms. Sie müssen in einem solchen Fall aufpassen, daß Sie die Fehlerquelle an der rich­ tigen Stelle im Druckmuster lokalisieren (Hilfestellungen dazu sind im Kapitel über die Übersetzung von Druckmustern zu finden). #on("b")#Beispiel#off("b")# Um die Verwendung von Abkürzungen zu demonstrieren, wollen wir folgendes Druckmuster betrachten: % VORSPANN Adressenliste als Beispiel für Abkürzungen Stand: &Datum ------------------------------------------ % ABKUERZUNGEN &Datum : date . % WIEDERHOLUNG &&l : &Vorname %Name &Strasse &&p& &Ort ------------------------------------------ % ABKUERZUNGEN &l : lfd nr . &p : f ("PLZ") . % NACHSPANN &l Adressen gedruckt. Dieses Beispiel enthält eine ganze Reihe interessanter Details. Als erstes sollten Sie registrieren, daß auch im Vorspann oder Nach­ spann Feldmuster verwendet werden können. Soll in diesem Fall ein Feldinhalt aus der EUDAS-Datei eingesetzt werden, so werden beim Vorspann die Inhalte des ersten und beim Nachspann die Inhalte des letzten durch Suchmuster ausgewählten Satzes verwendet. Daher kann auch jeder Abschnitt einen Abkürzungsteil haben. Abkürzun­ gen gelten jedoch für alle Abschnitte (s. '&l'); die Aufteilung in mehrere Abkürzungsteile fördert im wesentlichen die Übersichtlich­ keit. Versuchen Sie, an diesem Beispiel die wichtigsten Unterschiede zwischen dem #on("i")#Musterteil#off("i")# und dem #on("i")#Abkürzungsteil#off("i")# eines Abschnittes zu verstehen. Das Format des Musterteiles soll in die Ausgabe übernommen werden; daher ist dort die Stellung jedes Wortes wich­ tig. Im Abkürzungsteil definieren Sie Abkürzungen ohne bestimm­ tes Format - mit der einzigen Ausnahme, daß eine Abkürzungs­ definition mit einem '&' in der ersten Spalte anfangen und ein Leerzeichen vor dem Doppelpunkt haben muß. Wie Sie sehen, dürfen dort Leerzeilen zur besseren Lesbarkeit eingefügt werden. Sie sollten bei unserem Beispiel folgende Ausgabe erhalten: Adressenliste als Beispiel für Abkürzungen Stand: 28.12.84 ------------------------------------------ 1 : Herbert Wegner Krämergasse 12 5000 Köln ------------------------------------------ 2 : Helga Sandmann Willicher Weg 109 5300 Bonn 1 ------------------------------------------ 3 : Albert Katani Lindenstr. 3 5210 Troisdorf ------------------------------------------ 4 : Peter Ulmen Mozartstraße 17 5 Köln 60 ------------------------------------------ 5 : Karin Regmann Grengelweg 44 5000 Köln 90 ------------------------------------------ 6 : Hubert Arken Talweg 12 5200 Siegburg ------------------------------------------ 7 : Anna-Maria Simmern Platanenweg 67 5 Köln 3 ------------------------------------------ 8 : Angelika Kaufmann-Drescher Hauptstr. 123 53 Bonn 2 ------------------------------------------ 9 : Harald Fuhrmann Glockengasse 44 5000 Köln 1 ------------------------------------------ 10 : Friedrich Seefeld Kabelgasse 5000 Köln-Ehrenfeld ------------------------------------------ 10 Adressen gedruckt. Nun zu den Abkürzungen im einzelnen. Das Feld 'PLZ' muß abge­ kürzt werden, damit es rechtsbündig vor den Ort gedruckt werden kann. Die Abkürzung 'p' benutzt die im vorigen Kapitel beschriebe­ ne Form zur Abfrage des Feldinhaltes. 'Datum' wird als Abkürzung für das aktuelle Datum definiert, ein häufig benötigter Fall. 'date' ist der ELAN-Ausdruck, der das Datum liefert. (Bemerkung für ELAN-Programmierer: der Name der Abkürzung gehorcht nicht der ELAN-Syntax für Bezeichner). Eine für Tabellen sinnvolle Funktion wird bei der Definition von 'l' verwendet. Der von EUDAS definierte Ausdruck 'lfd nr' lie­ fert die laufende Nummer des gerade gedruckten Satzes als Text. Dabei ist zu beachten, daß die laufende Nummer nicht mit der Satz­ nummer übereinstimmt, sondern nur während des Druckvorganges von 1 an bei jedem gedruckten Satz hochgezählt wird. Diese Funk­ tion dient dazu, die Sätze in der Liste durchzunumerieren. Die laufende Nummer soll in der Liste rechtsbündig mit Doppel­ punkt vor dem Namen stehen. Dazu wird das Feldmuster '&&l' be­ nutzt, eine Form, die eigentlich keinen Sinn hat (die Kombination 'variable Länge' und 'rechtsbündig' gibt es nicht). Um ein möglichst kurzes Feldmuster schreiben zu können, wird in diesem Fall jedoch feste Länge unterstellt (auch ohne folgendes '&'). Damit hat das kürzeste Feldmuster fester Länge drei Zeichen sowohl im linksbün­ digen ('&l&') wie auch im rechtsbündigen Fall ('&&l'). #on("b")#Auswertungen#off("b")# Die Verwendung der Abkürzung 'l' im Nachspann kann als erstes Beispiel für eine Auswertungsfunktion gelten. Da für den Nachspann die Daten des letzten Satzes verwendet werden, erscheint hier die laufende Nummer des letzten Satzes und somit die Anzahl der Sätze, die gedruckt wurden. Das kann dazu benutzt werden, die Sätze zu zählen, die eine bestimmte Suchbedingung erfüllen. Folgendes Druckmuster zählt die Anzahl der Frauen oder Männer in der Datei: % NACHSPANN &l Personen mit dem Geschlecht '%' vorhanden. % ABKUERZUNGEN &l : lfd nr . Wenn Sie vor dem Drucken jetzt die Suchbedingung 'm' für das Feld 'm/w' einstellen, werden alle Männer ausgewählt. Das Drucken be­ steht in diesem Fall nur aus dem Hochzählen der laufenden Nummer für jeden Mann. Im Nachspann kann das Ergebnis dann ausgegeben werden; zugleich soll der aktuelle Wert des Feldes 'm/w' gedruckt werden, damit das Druckmuster auch für das Zählen der Frauen verwendet werden kann. Die beiden möglichen Ausgaben würden dann so aussehen: 6 Personen mit dem Geschlecht 'm' vorhanden. 4 Personen mit dem Geschlecht 'w' vorhanden. #on("b")#Zusammenfassung#off("b")# Wir können die Erkenntnisse dieses Abschnittes wie folgt zusammenfassen: * Feldmuster können auch im Vorspann und Nachspann verwendet werden. Im Vorspann werden die Daten des ersten, im Nachspann die Daten des letzten ausgewählten Satzes verwendet. * Der Musterteil eines Abschnittes definiert ein Format; der Ab­ kürzungsteil ist formatfrei. * 'lfd nr' dient zum Durchnumerieren aller gedruckten Sätze. * Ein rechtsbündiges Feldmuster hat immer auch feste Länge. #on("b")#Komplexe Abkürzungen#off("b")# Mit Hilfe von Abkürzungen können wir jetzt auch bessere Musterbriefe schreiben. Ein Problem, das bereits angesprochen wurde, besteht darin, daß in der Anrede je nach Ge­ schlecht 'Herr' oder 'Frau' stehen soll. Um dieses Problem zu lösen, wird der Inhalt des Feldes 'm/w' benötigt. Da in einer Abkürzung jede ELAN-Anweisung erlaubt ist, die einen Text liefert, können natürlich auch #on("i")#IF-Anweisungen#off("i")# verwen­ det werden. Mit diesen Informationen können wir jetzt die Abkür­ zung 'Anrede' definieren: % ABKUERZUNGEN &Anrede : IF f ("m/w") = "w" THEN "Frau" ELSE "Herr" END IF . Für Nicht-Programmierer: Die IF-Anweisung besteht aus einer Ab­ frage und zwei Alternativen. Die Abfrage steht zwischen dem IF und dem THEN und besteht in der Regel aus einer Abfrage, ob zwei Dinge gleich oder ungleich (<>), größer oder kleiner sind. Außerdem können mehrere Abfragen mit AND (und) und OR (oder) kombiniert werden. Näheres dazu im Kapitel 14. Die Alternative hinter dem THEN wird ausgewählt, wenn die Abfrage zutrifft. An dieser Stelle sind wieder beliebige Ausdrücke erlaubt, die einen Text liefern, einschließlich erneuter IF-Anwei­ sungen (Schachtelung). Die Alternative zwischen ELSE und END IF wird ausgewählt, wenn die Abfrage nicht zutrifft. #on("b")#Textkonstanten#off("b")# Bisher wurden nur ELAN-Funktionen als Textlie­ feranten betrachtet ('date', 'lfd nr', 'f'). In unserem Fall werden aber #on("i")#Textkonstanten#off("i")# in den Alternativen der IF-Anweisung benö­ tigt. Textkonstanten werden in ELAN in Anführungsstriche einge­ schlossen, die aber nicht zum Text gehören. Innerhalb einer Text­ konstanten werden Leerzeichen wie alle anderen Zeichen angesehen (erscheinen also auch nachher in der Ausgabe). Bei solchen Abkürzungen, die längere Anweisungen umfassen, sollten Sie das freie Format ausnutzen und eine möglichst über­ sichtliche Darstellung wählen. Wie Sie sehen, muß nur der Doppel­ punkt noch in der ersten Zeile stehen, der Rest kann sich beliebig auf die folgenden Zeilen erstrecken. #on("b")#Beispiel#off("b")# Ein typischer Einsatz einer IF-Anweisung für die Anrede sieht so aus: % WIEDERHOLUNG Sehr geehrte&Anrede %! ... % ABKUERZUNGEN &Anrede : IF f ("m/w") = "m" THEN "r Herr" ELSE " Frau" END IF . Sie sollten jetzt diese Konstruktion in einen Musterbrief einfügen können. Probieren Sie ihn dann als Beispiel aus ! #on("b")#Weitere Möglichkeiten#off("b")# Durch Verwendung von Abkürzungen ist es auch möglich, rechtsbündige Felder mit einer Länge von weniger als 3 Zeichen zu simulieren. Dies geschieht mit Hilfe der Textoperatio­ nen von ELAN. Ohne ELAN-Vorkenntnisse können Sie dieses Bei­ spiel überlesen. In unserer Liste im obigen Beispiel sind die laufen­ den Nummern höchstens zweistellig und sollten deshalb auch nur zwei Stellen belegen. Dies würde folgende Abkürzung ermöglichen: % ABKUERZUNGEN &l : text (lfd nr als zahl, 2) . lfd nr als zahl : int (lfd nr) . Die Prozedur 'text' wird dazu benutzt, eine Zahl rechtsbündig auf zwei Stellen zu formatieren (s. EUMEL-Benutzerhandbuch). Da die Abkürzung immer eine Länge von zwei Zeichen hat, kann sie auch in einem Feldmuster variabler Länge eingesetzt werden. Die Attribute 'feste Länge' und 'rechtsbündig' werden in diesem Fall also nicht durch das Feldmuster, sondern durch die Abkürzung selbst erzeugt. Um die Prozedur 'text' anwenden zu können, muß die laufende Nummer als Zahl (sprich: INT-Objekt) vorliegen. Diese Umwandlung wird mit der Prozedur 'int' vorgenommen, die einen Text in eine Zahl umwandelt. Obwohl man 'int (lfd nr)' direkt in den Aufruf von 'text' hätte schreiben können, wird hier als Demonstration dafür ein Refinement verwendet. Refinements können in einem Abkürzungsteil neben Abkürzun­ gen stehen und von allen Abkürzungen benutzt werden. Sie werden ähnlich geschrieben wie Abkürzungen, nur ihr Name muß in Klein­ buchstaben geschrieben werden, dafür muß er nicht in der ersten Spalte anfangen und kann Leerzeichen enthalten. Bei komplizierte­ ren Ausdrücken sollten Refinements zur besseren Lesbarkeit einge­ setzt werden. Sie können die IF-Anweisung auch mit beliebig vielen ELIF- Teilen versehen. Achten Sie jedoch darauf, daß die IF-Anweisung #on("i")#immer#off("i")# irgendeinen Wert liefern muß. Sie dürfen also den ELSE-Teil nicht weglassen. Statt einer IF-Anweisung können Sie natürlich auch eine SELECT-Anweisung verwenden. Es stehen Ihnen im Prin­ zip alle werteliefernden Anweisungen von ELAN zur Verfügung. Die Programmiersprache ELAN bietet Ihnen noch weit mehr Möglichkeiten, als hier beschrieben werden können. So können Sie sich eigene Prozeduren definieren und diese dann in Abkürzungen verwenden. In Kapitel 14 und 15 finden Sie eine Einführung in die wichtigsten Konstrukte, die für EUDAS gebraucht werden. 13.2 Bedingte Musterteile Wenn größere Teile des Druckmusters in Abhängigkeit von bestimm­ ten Daten unterschiedlich ausfallen sollen, werden die dazu benö­ tigten Abkürzungen sehr umfangreich. Für solche Fälle kann man IF-Anweisungen auch im Musterteil eines Abschnitts verwenden. In diesem Fall werden die Alternativen der IF-Anweisung durch Musterzeilen dargestellt. Im Musterteil müssen jedoch die Zeilen, die Teil der IF-An­ weisung sind, von den Musterzeilen unterschieden werden. Deshalb werden die Anweisungszeilen durch ein '%'-Zeichen in der ersten #on("i")#und#off("i")# zweiten Spalte gekennzeichnet. Das zweite '%'-Zeichen dient zur Unterscheidung von Anweisungen an den Druckgenerator, die nicht an den ELAN-Compiler übergeben werden sollen. Mit einer IF-Anweisung im Musterteil kann man das Anredepro­ blem auch folgendermaßen lösen: % WIEDERHOLUNG %% IF f ("m/w") = "w" THEN Sehr geehrte Frau &! %% ELSE Sehr geehrter Herr &! %% END IF; Beachten Sie den Unterschied, daß die IF-Anweisung hier mit einem Semikolon abgeschlossen werden muß - in Abkürzungen mußte ja ein Punkt danach folgen. Außerdem darf hier der ELSE-Teil (die zweite Alternative) fehlen, während in einer Abkürzung in jeder Alternati­ ve etwas stehen muß (zumindest der leere Text ""). Falls sich der IF-THEN-Teil über mehr als eine Zeile erstrek­ ken soll, muß jede dieser Zeilen mit '%%' beginnen, da die Folgezei­ len sonst als Musterzeilen gedruckt würden. Benutzen Sie in einem solchen Fall jedoch besser ein Refinement, das Sie im Abkürzungs­ teil definieren müssen. Sie können im Musterteil auch andere ELAN-Anweisungen verwenden. Der Unterschied zu Abkürzungen liegt darin, daß die Musterzeilen nicht als Werte angesehen werden, die die Anweisung liefern muß, sondern als Anweisungen, die dort aufgeführten Mu­ sterzeilen einzusetzen und zu drucken. Daher kann im Musterteil auch eine FOR-Schleife sinnvoll sein, wenn in Abhängigkeit eines Wertes eine bestimmte Anzahl von Zeilen gedruckt werden soll. 13.3 Übersetzung Wenn Sie bis jetzt auch als ELAN-Programmierer immer noch nicht ganz durchblicken, wie Sie welche ELAN-Anweisungen verwenden können, dann ist das noch kein Anlaß zur Sorge. Es ist kaum mög­ lich, die genauen Auswirkungen beliebiger Anweisungen zu be­ schreiben, ohne den Übersetzungsprozeß zu schildern, der diese Anweisungen zu einem ELAN-Programm zusammenbindet. Daher soll diese Übersetzung jetzt genauer erklärt werden. #on("b")#Übersetzungsmechanismus#off("b")# Alle Zeilen eines Abkürzungsteils wer­ den direkt in das Programm übernommen, wobei der Name einer Ab­ kürzung durch einen beliebig gewählten Refinementnamen ersetzt wird ('abk' + eine laufende Nummer). Alle Abkürzungen und Re­ finements werden als globale Refinements definiert, also außerhalb von Prozeduren. Dadurch wird erreicht, daß sie an jeder Stelle verwendet werden können. Damit eine Abkürzung richtig als Refinement übersetzt wird, muß sie ein TEXT-Objekt als Wert liefern. Die anderen Refinements sind beliebig, da Sie nur in selbstdefinierten Anweisungen verwen­ det werden. Die Refinements der Abkürzungen werden in einer Zu­ weisung an eine TEXT-Variable verwendet, damit der Druckgenera­ tor auf den entsprechenden Wert zugreifen kann. Jeder Abschnitt wird dagegen als eine Prozedur übersetzt. Jede Folge von Musterzeilen wird in eine Anweisung übersetzt, diese Musterzeilen einzusetzen und zu drucken. Jede '%%'-Anweisung wird einfach unverändert dazwischen geschrieben. Die Vorspann- Prozedur wird einmal zu Anfang aufgerufen, die Prozedur für den Wiederholungsteil einmal für jeden ausgewählten Satz und die Nach­ spann-Prozedur einmal am Schluß. Bei Fehlern im ELAN-Teil zeigt der Compiler das erzeugte Pro­ gramm zusammen mit seinen Fehlermeldungen im Paralleleditor. Sie müssen nun die Fehlermeldung lokalisieren und anhand der eben gegebenen Hinweise in das ursprüngliche Druckmuster zurücküber­ setzen, damit Sie dort den Fehler korrigieren können. #on("b")#Beispiel#off("b")# Nun müßten Sie genug Informationen haben, um beliebige ELAN-Anweisungen in das Druckmuster einfügen zu können. Als Beispiel wollen wir versuchen, alle Männer und Frauen in der Adressendatei zu zählen, ohne ein Suchmuster einstellen zu müssen und ohne den Druckvorgang zweimal ablaufen zu lassen (wie dies bei dem obigen Beispiel der Fall war). Ein erster Versuch könnte so aussehen: % VORSPANN %% INT VAR maenner, frauen; %% maenner := 0; %% frauen := 0; % WIEDERHOLUNG %% IF f ("m/w") = "m" THEN %% maenner INCR 1 %% ELSE %% frauen INCR 1 %% END IF % NACHSPANN &maenner Männer und %frauen Frauen vorhanden. Aber Vorsicht! In diesem Beispiel sind mehrere Fehler eingebaut. Finden Sie sie! #on("b")#Fehler im Beispiel#off("b")# Der erste Fehler befindet sich im Nachspann. Hier wird versucht, die Namen der beiden Variablen 'maenner' und 'frauen' direkt in einem Feldmuster zu verwenden. Diese beiden Namen sind dem Druckgenerator nicht bekannt, sondern nur dem ELAN-Compiler. Um die Werte der beiden Variablen einsetzen zu können, müssen Sie also zwei geeignete Abkürzungen definieren. Der zweite Fehler ist schwieriger zu finden. Wie oben gesagt, wird jeder Abschnitt in eine Prozedur übersetzt. Die in einem Ab­ schnitt definierten Variablen können also nur in diesem Abschnitt verwendet werden (sie sind lokal) und auch nicht im Abkürzungs­ teil, da dieser wieder global vereinbart wird. Die beiden im Vor­ spann definierten Variablen stehen also im Wiederholungsteil und im Nachspann nicht zur Verfügung. #on("b")#Anweisungen im Initialisierungsteil#off("b")# Für diesen Fall gibt es die Möglichkeit, ELAN-Anweisungen vor allen Abschnitten im Initiali­ sierungsteil zu definieren. Diese Anweisungen sind dann ebenfalls global. Das richtige Druckmuster finden Sie auf der nächsten Seite. Natürlich könnten Sie die Initialisierung der beiden Variablen auch noch aus dem Vorspann herausnehmen. Denken Sie daran, daß Sie aus INT-Variablen erst einen Text machen müssen, ehe Sie sie in eine Musterzeile einsetzen können. Beachten Sie Schreibweise der Variablen: in ELAN können die Umlaute nicht in Bezeichnern ver­ wendet werden, daher muß die Variable mit 'ae' geschrieben wer­ den. Im Mustertext und in Abkürzungs- und Feldnamen können die Umlaute jedoch frei verwendet werden. %% INT VAR maenner, frauen; % VORSPANN %% maenner := 0; %% frauen := 0; % WIEDERHOLUNG %% IF f ("m/w") = "m" THEN %% maenner INCR 1 %% ELSE %% frauen INCR 1 %% END IF % NACHSPANN &m Männer und %f Frauen vorhanden . % ABKUERZUNGEN &m : text (maenner) . &f : text (frauen) . 13.4 Gruppen Der Druckgenerator bietet die Möglichkeit, Vorspann und Nachspann nicht nur am Anfang und am Ende, sondern auch an bestimmten Stellen zwischen Sätzen zu drucken. Diese Stellen sind dadurch bestimmt, daß ein bestimmtes Merkmal (z.B. ein Feldinhalt) seinen Wert ändert. Ein solches Merkmal wird im Druckmuster #on("i")#Gruppe#off("i")# ge­ nannt. Ein Beispiel für die Verwendung von Gruppen ist eine Schüler­ datei, die nach Klassen geordnet ist. Definiert man das Feld 'Klas­ se' als Gruppe, so wird jeweils am Ende einer Klasse ein Nachspann und am Beginn einer Klasse ein Vorspann gedruckt. Dieses Verfahren ist eine Erweiterung der bisher beschriebenen Methode, indem eine Datei quasi in mehrere Dateien untergliedert wird, die jedoch in einem Arbeitsgang gedruckt werden können. Voraussetzung dafür ist jedoch, daß die Datei nach dem Gruppen­ merkmal geordnet ist - der Druckgenerator sammelt nicht erst alle Schüler einer Klasse aus der Datei, sondern erwartet sie hinter­ einander. #on("b")#Gruppendefinition#off("b")# Eine Gruppe wird im Initialisierungsteil des Druckmusters (also vor allen Abschnitten) definiert. Notwendige Daten sind eine Nummer zur Identifizierung und das Merkmal. Die Nummer sollte am sinnvollsten von 1 an vergeben werden; die mög­ lichen Werte sind nach oben hin beschränkt. Das Merkmal ist ein beliebiger ELAN-Ausdruck, der einen Text liefert. Sinnvollerweise wird er den Inhalt eines Feldes enthalten. Gruppendefinitionen müssen nach allen ELAN-Anweisungen im Initialisierungsteil folgen, und zwar, weil die Gruppendefinitionen alle in einer Prozedur zusammengefaßt werden, die bei jedem neuen Satz auf Gruppenwechsel testet. Unter der Annahme, daß die oben erwähnte Schülerdatei ein Feld 'Klasse' besitzt, würde die Gruppe wie folgt definiert: % GRUPPE 1 f ("Klasse") Nach der Anweisung 'GRUPPE' folgt die Gruppennummer und dann ein ELAN-Ausdruck. Die ganze Definition muß in einer Zeile stehen; reicht der Platz nicht aus, müssen Sie in einem Abkürzungsteil ein Refinement definieren. #on("b")#Klassenliste#off("b")# Das komplette Druckmuster für die Klassenliste könn­ te folgendes Aussehen haben, wenn außer 'Klasse' auch noch die Felder 'Name' und 'Vorname' vorhanden sind: % GRUPPE 1 f ("Klasse") % VORSPANN Klassenliste für Klasse &Klasse ---------------------------- % WIEDERHOLUNG &Vorname %Name % NACHSPANN \#page\# Wenn eine Gruppe definiert ist, werden im Nachspann immer die Feldinhalte des letzten Satzes vor dem Gruppenwechsel gedruckt, im Vorspann die Inhalte des ersten Satzes nach dem Wechsel. Daher kann hier im Vorspann die Klasse gedruckt werden, da sie sich erst ändert, wenn schon wieder der nächste Vorspann gedruckt wird. #on("b")#Mehrere Gruppen#off("b")# Wie die Identifikation über eine Gruppennummer vermuten läßt, können Sie mehrere Gruppen definieren. Nachspann und Vorspann werden jeweils gedruckt, wenn sich das Merkmal ir­ gendeiner Gruppe ändert. Ob eine bestimmte Gruppe gewechselt hat, kann mit der Abfrage BOOL PROC gruppenwechsel (INT CONST gruppennummer) in einer IF-Anweisung ermittelt werden. Vor dem ersten und nach dem letzten Satz wechseln automatisch alle Gruppen. Die ganze Datei bildet eine Quasi-Gruppe mit der Nummer 0. Sie ist immer definiert und wechselt nur vor dem ersten und nach dem letzten Satz. Sie ist es, die bewirkt, daß Vorspann und Nach­ spann in ihrer normalen Weise gedruckt werden. #on("b")#Anwendungsbeispiel#off("b")# Um einige der Möglichkeiten zu illustrieren, die durch Gruppen geschaffen werden, wollen wir als Beispiel eine Anwendung betrachten, die neue Wege für die Benutzung von EUDAS aufzeigt. Aus einer Datei, in der für jede Bestellung der Kunde, der Ar­ tikel, die bestellte Menge und der Einzelpreis des Artikels einge­ tragen werden, sollen anschließend Rechnungen gedruckt werden. Die Datei soll folgende Felder haben: 'Kundennummer' 'Artikelnummer' 'Einzelpreis' 'Menge' Als Voraussetzung müssen die Bestellungen in der Datei jeweils nach Kunden geordnet vorliegen. Die Kundennummer wird als Gruppe definiert, so daß die Bestellungen eines Kunden zu einer Rechnung zusammengefaßt werden können. Das Druckmuster rechnet dann die einzelnen Preise zusammen und gibt eine Endsumme aus. Damit in der Rechnung Name und Adresse des Kunden auftau­ chen können, wird zu der Bestellungsdatei die Kundendatei gekop­ pelt, die folgende Felder haben soll: 'Kundennummer' 'Name' 'Vorname' 'Strasse' 'PLZ' 'Ort' Stellen Sie sich zum Ausprobieren des folgenden Druckmusters ge­ gebenenfalls eigene Daten zusammen. Hier nun das Druckmuster: %% REAL VAR gesamtpreis, summe; % GRUPPE 1 f ("Kundennummer") % VORSPANN %% summe := 0.0; Fa. Kraus & Sohn Schotterstr. 10 5000 Köln 1 &Vorname %Name &Strasse &PLZ &Ort &Datum R E C H N U N G =============== Menge Artikelnr. Einzelpreis Gesamtpreis ------------------------------------------------ % ABKUERZUNGEN &Datum : date . % WIEDERHOLUNG %% gesamtpreis := round %% (wert ("Einzelpreis") * wert ("Menge"), 2); %% summe INCR gesamtpreis; &Menge &Artikelnummer &&&&epr&& &&&&gpr&& % ABKUERZUNGEN &epr : f ("Einzelpreis") . &gpr : zahltext (gesamtpreis, 2) . % NACHSPANN ------------------------------------------------ Summe: &&&&sum&& + 14% MWSt. &&&Mwst&& ========= Endbetrag &&&&end&& \#page\# % ABKUERZUNGEN &sum : zahltext (summe, 2) . &Mwst : zahltext (mwst, 2) . &end : zahltext (summe + mwst, 2) . mwst : round (summe * 0.14, 2) . Im Initialisierungsteil dieses Druckmusters wird die Kundennummer als Gruppe definiert. Dies hat zur Folge, daß für jeden neuen Kun­ den eine neue Rechnung begonnen wird, nachdem vorher im Nach­ spann die Rechnungssumme des vorherigen Kunden berechnet und ausgedruckt wurde. Vor dieser Gruppendefinition sind 'gesamtpreis' und 'summe' definiert, die später als globale Variablen zur Verfü­ gung stehen sollen. Diese Zeile darf nicht nach der Gruppendefini­ tion stehen. Im Vorspann wird der Kopf der Rechnung angegeben. Dieser enthält neben den Daten des Kunden (aus der gekoppelten Kun­ dendatei) noch das Datum. Die Kundennummer wird nur zum Kop­ peln und als Gruppenmerkmal benötigt, erscheint also nicht auf der Rechnung. Es fällt auf, daß im Firmennamen ein '&'-Zeichen auftaucht, das doch für die Markierung von Feldmustern reserviert ist. Die beiden Musterzeichen können jedoch im normalen Text auftauchen, wenn ihnen direkt ein Leerzeichen folgt. In diesem Fall werden Sie nicht als Beginn eines Feldmusters interpretiert, sondern unverän­ dert gedruckt. Der gleiche Fall taucht noch mit '%' im Nachspann auf. Im Wiederholungsteil wird zunächst aus dem Einzelpreis und der Menge des jeweiligen Artikels der Gesamtpreis für diesen Artikel berechnet. Für die Abfrage der Feldinhalte wird die Funktion 'wert' verwendet, die wie 'f' funktioniert, jedoch gleich einen REAL-Wert liefert. Zu beachten ist, daß 'wert' wie beim Sortieren von Zahl alle Sonderzeichen ignoriert. Weiterhin müssen die Zahlen mit dem ein­ gestellten Dezimalkomma geschrieben werden (also normalerweise mit Komma), damit ihr Wert richtig erkannt wird. Anderenfalls soll­ ten Sie den Dezimalpunkt einstellen (s. 11.1). Damit kaufmännisch richtig gerechnet wird, wird der Gesamt­ preis auf 2 Nachkommastellen gerundet und erst dann aufsummiert. Würde der Gesamtpreis nur zum Einsetzen gerundet, könnten bei der anschließenden Addition der nicht gerundeten Werte eine falsche Gesamtsumme entstehen. Erst nach diesen Berechnungen kann die Musterzeile folgen, in die die Werte dann eingesetzt werden. Um eine Ausgabe mit zwei Nachkommastellen zu erzeugen, wird die von EUDAS definierte Funktion 'zahltext' benutzt. Diese erzeugt aus einem REAL-Wert einen Text mit der angegebenen Anzahl von Kommastellen und setzt das korrekte Dezimalkomma ein. Das Ergebnis dieser Funktion wird dann rechtsbündig eingesetzt. Im Nachspann wird dann der summierte Wert mit aufgeschlage­ ner Mehrwertsteuer gedruckt. Die Mehrwertsteuer muß ebenfalls auf zwei Nachkommastellen gerundet werden. #on("b")#Erweiterung#off("b")# Zur Erweiterung könnten Sie die Bestelldatei noch mit einer Artikeldatei koppeln, die etwa folgende Struktur haben würde: 'Artikelnummer' 'Bezeichnung' 'Einzelpreis' In diesem Fall könnten Sie noch jeweils die Artikelbezeichnung in eine Rechnungszeile drucken. Außerdem würde der Preis zentral gespeichert. Eine entsprechende Änderung des Druckmusters sollte Ihnen keine Schwierigkeiten bereiten.