Als Nächstes wenden wir uns der Welt der Zahlen zu. Erfahren Sie in diesem Kapitel, wie Sie Berechnungen in ABAP-Programmen durchführen. 4 Felder und Berechnungen Sie sollten mit allem rechnen – im SAP-System können Sie das sogar mit Datumswerten und Zeichenketten. In diesem Kapitel beginnen wir jedoch mit dem Einfachsten: dem Rechnen mit Zahlen. Vorbereitungen Bevor wir beginnen, sollten Sie entscheiden, ob Sie für die ersten Berechnungen in ABAP einen neuen Report anlegen oder diese einfach in unserem Report aus Kapitel 3, »Programmieren im ABAP Editor«, einbauen. Beides ist natürlich möglich – doch nicht zuletzt für eine bessere Übersichtlichkeit sollten Sie mit einem frischen Report arbeiten. Die Neuanlage eines Reports wird in Abschnitt 3.1, »ABAP-Report anlegen«, beschrieben. Als Alternative können Sie aber auch einen bestehenden Report kopieren und ihn anschließend modifizieren. Auf diese Weise bleibt der alte Report erhalten, und der neue wird unter einem eigenen Namen abgespeichert. 4.1 Report vorbereiten Starten Sie im Einstiegsbild für den ABAP Editor (SAP Menü 폷 Werkzeuge 폷 ABAP Workbench 폷 Entwicklung 폷 ABAP Editor). Im Startbildschirm geben Sie als Programmnamen den Namen unseres letzten Reports ein, »Z_TEILNEHMERLISTE01«. Anschließend können 107 Report kopieren und modifizieren 4 Felder und Berechnungen Report vorbereiten Sie entweder über Programm 폷 Kopieren oder über den Button Kopieren ( , (Strg) + (F5)) den Kopiervorgang starten (siehe Abbildung 4.1). Abbildung 4.3 Elemente eines ABAP-Reports mit kopieren Abbildung 4.1 ABAP-Programm kopieren Sie werden nach dem Namen des Zielprogramms gefragt (siehe Abbildung 4.2). Dieser muss sich vom Namen des Quellprogramms unterscheiden, und es gelten für ihn selbstverständlich auch die Namenskonventionen, wie sie in Abschnitt 2.1.2, »Tabelle anlegen und pflegen«, beschrieben werden. Abbildung 4.2 Namen eines Zielprogramms auswählen Haben Sie den Namen des Zielprogramms eingetragen, setzen Sie den Kopiervorgang über die Schaltfläche Kopieren oder die (¢)-Taste fort. Anschließend haben Sie die Wahl, neben dem Quellcode und den Textelementen auch andere Elemente des alten Programms mit zu kopieren (siehe Abbildung 4.3). 108 Für den Anfang können Sie, ohne ein Häkchen zu setzen, einfach über die Schaltfläche Kopieren den Prozess fortführen und unseren neuen Report als Lokales Objekt abspeichern. Das System zeigt Ihnen anschließend wieder das Einstiegsbild des ABAP Editors mit dem neuen Programmnamen. Das alte Programm wurde mit allen gewählten Elementen kopiert; beachten sollten Sie nur, dass der neue Quellcode noch inaktiv ist. Elemente kopieren Hätten Sie beispielsweise für den alten Quellcode eine Dokumentation hinterlegt, könnte diese ausgewählt und kopiert werden. Alle Elemente dieses Fensters sind keine eigenen Objekte der Datenbank, sondern hängen fest am Report, d. h., dass beispielsweise die Dokumentation für den Report nicht mehrfach verwendbar ist (etwa für andere Reports), wie es bei einem Datenelement der Fall wäre. Ein Datenelement ist dagegen ein eigenes Objekt und damit mehrfach verwendbar. Über den Ändern-Button ( ) gelangen Sie in den Änderungsmodus für den Quellcode. Was Sie jetzt sehen, ist nicht neu: Den alten Quellcode kennen Sie bereits. Auffallen könnte Ihnen aber, dass die REPORT-Anweisung nicht mehr ganz korrekt ist. Sie wurde zwar richtig kopiert, doch da sich der Programmname im Operanden geändert hat, sollte es der erste Arbeitsschritt im neuen Quellcode sein, den Namen auf unseren neuen Programmnamen umzuschreiben: Z_TEILNEHMERLISTE02. 109 4.1 4 Felder und Berechnungen Report vorbereiten 4.1 Zeilenblock in Kommentarzeilen umwandeln Was machen Sie mit den Programmzeilen, die Sie nicht mehr benötigen? Es gibt zwei Möglichkeiten: Entweder Sie löschen die Zeilen, oder Sie wandeln sie in Kommentarzeilen um (»auskommentieren«). Vorsichtige Entwickler werden sich zunächst für die zweite Möglichkeit entscheiden, vermeintlich überflüssige Anweisungen in Kommentarzeilen umzuwandeln, die man vielleicht für die eine oder die andere Anweisung doch noch einmal braucht – man kann ja nie wissen. Deshalb gehen auch wir so vor und wandeln vorsichtshalber zunächst die alten Anweisungen in Kommentarzeilen um. Hierzu markieren Sie mit dem Cursor den zu bearbeitenden Zeilenblock wie in jedem Editor üblich mit den Cursortasten oder mit der Maus. Der markierte Block wird nun dunkelblau hinterlegt dargestellt (siehe Abbildung 4.4) Abbildung 4.5 Block in Kommentarzeilen umwandeln Aus Abbildung 4.5 können Sie auch ableiten, wie Sie bei Bedarf einen Block von Kommentarzeilen analog wieder in Anweisungszeilen umwandeln: Hierzu markieren Sie den Block sowie das Blockende und wählen Hilfsmittel 폷 Block/Ablage 폷 Kommentar-* löschen. Da wir für die Anweisungen ab Zeile 10 aber tatsächlich im Folgenden keine Verwendung mehr haben, können Sie den Zeilenblock ruhig löschen. Hierfür markieren Sie zunächst wieder den entsprechenden Block und drücken dann die (Entf)-Taste auf Ihrer Tastatur. Abbildung 4.4 Block markieren Anschließend wandeln Sie über Hilfsmittel 폷 Block/Ablage 폷 Kommentar-* einfügen den gesamten Block in Kommentarzeilen um (siehe Abbildung 4.5). Als Ergebnis sind alle Zeilen des Blocks in Spalte 1 mit einem Stern als Kommentarzeilen gekennzeichnet. War eine Zeile bereits vorher eine Kommentarzeile, hat sie jetzt zwei führende Sterne. 110 Zeilenblock löschen Sichern nicht vergessen! Vergessen Sie nicht, die Veränderung am Quellcode nach wichtigen Arbeitsschritten oder vor Arbeitspausen über den Sichern-Button ( ) zu speichern. Wir können uns nun der eigentlichen Aufgabe dieses Kapitels zuwenden: Wir verarbeiten nun zwei Zahlen mit ABAP mithilfe der vier 111 Spreu vom Weizen trennen 4 Felder und Berechnungen Grundrechenarten und schreiben das Ergebnis in eine Liste. Hierzu sind drei Arbeitsschritte erforderlich: 1. die Felder für die Zahlen deklarieren 2. das Ergebnis berechnen 3. das Ergebnis ausgeben Die Namen der Variablen sollten darüber hinaus sprechend, d. h. selbsterklärend sein. Nennen Sie die Variable für einen Familiennamen z. B. FAMILIENNAME und nicht A1. Legen Sie großen Wert auf Lesbarkeit, und seien Sie dementsprechend gnädig mit Dritten – Sie könnten es in wenigen Wochen selbst sein. Wie in der Praxis müssen auch bei unserer Teilnehmerverwaltung Inhalte einer oder mehrerer Tabellen im Report durch Berechnungen weiterverarbeitet, ergänzt oder ausgewertet werden. Hierzu benötigen wir im Report eigene Felder. Auch ABAP verfügt über Regeln, auf welche Weise Felder verarbeitet werden. Das System muss die Zahlen in unserem Beispiel zwischenspeichern, ablegen und sie sich für folgende Verarbeitungsschritte wieder zurückholen. Hierzu werden die Werte an einem Ort bzw. einer Datenadresse im Speicher temporär abgelegt. Sollen sich die Inhalte unserer Zahlenfelder verändern können, deklarieren wir für den Einstieg unsere Felder mit der DATA-Anweisung. Für unsere Berechnungen bieten sich vorerst zwei Datentypen für die Variablen an, nämlich ganze Zahlen (Integer) und Dezimalzahlen. DATA In ABAP heißen diese Orte Felder oder Datenobjekte. Sind die Inhalte der Datenobjekte durch ABAP-Anweisungen veränderbar, spricht man von Variablen, sind sie es nicht, spricht man von Konstanten. Soll das Feld ZAHL01 eine ganze Zahl enthalten, lautet die Anweisung folgendermaßen: TYPE i 4.2.1 Namen vergeben Sprechende Variablen Felder haben einen symbolischen Namen (z. B. ZAHL01), eine definierte Länge und einen Datentyp. Über die symbolischen Namen werden die Speicheradressen angesprochen, und die dort abgelegten Inhalte können gelesen und verarbeitet werden. Für die Verarbeitung gelten je nach Datentyp entsprechende Regeln, die allerdings von Programmiersprache zu Programmiersprache sehr unterschiedlich sind. 4.2 Felder verarbeiten Felder deklarieren Felder deklarieren Variablen deklarieren Bei der Namensvergabe für Variablen müssen Sie Folgendes beachten: 왘 Der Name soll mit einem Buchstaben beginnen; er darf nicht ausschließlich aus Ziffern bestehen. 왘 Der Name darf maximal 30 Zeichen lang sein. 왘 Der Name soll möglichst keine Sonderzeichen enthalten, bis auf den Unterstrich. Ausdrücklich verbotene Sonderzeichen sind Plus (+), Komma (,), Doppelpunkt (:), Klammer auf (() und Klammer zu ()). 왘 Für den Namen dürfen keine reservierten Wörter für ABAP-Anweisungen oder Zusätze verwendet werden. 112 DATA zahl01 TYPE i. Soll das Feld ZAHL01 hingegen eine Dezimalzahl mit zwei Nachkommastellen sein, lautet die Anweisung: DATA zahl01 TYPE p DECIMALS 2. Bei der Entscheidung, welche Deklaration sinnvoller ist, kommt es demnach auf den Verwendungszweck an. Felder vom Typ i werden üblicherweise für Zähler oder Stückzahlen verwendet. Felder vom Typ p sind für arithmetische Berechnungen mit Nachkommastellen üblich. Wichtig ist, vor der weiteren Programmierung zu überlegen, welche Rechen- und Anzeigegenauigkeit bei der gewünschten Berechnung erforderlich ist, weil sich die Zahl der nötigen Nachkommastellen hiernach richtet – denken Sie z. B. an Wechselkurse. Fünf Nachkommastellen sind in solchen Fällen keine Seltenheit, wogegen die 14 erlaubten Nachkommastellen eher selten ausgereizt werden. 113 TYPE p 4.2 4 Felder und Berechnungen Elementare Datentypen Beide Datentypen, i und p, sind für ABAP elementare Datentypen mit fester Länge. Deshalb müssen Sie die Feldlänge hier nicht explizit angeben. Die beiden Datentypen sind zwei von acht dieser in ABAP eingebauten elementaren Datentypen fester Länge. Umfassenderes Typkonzept Einen elementaren Datentyp variabler Länge werden Sie noch kennenlernen. Für ein leichteres Verständnis beschränken wir uns vorerst auf die wichtigsten Datentypen. Auf die Darstellung von Referenzdatentypen und komplexen Datentypen wird verzichtet. Sie sollten jedoch im Hinterkopf behalten, dass das Typkonzept in ABAP für fortgeschrittene Anwendungen viel umfassender ist, als hier dargestellt. Möchten Sie zwei Variablen gleichlautend deklarieren, müssen Sie zwei Anweisungszeilen schreiben und darauf achten, dass Sie dieselben Attribute verwenden, beispielsweise: DATA zahl01 TYPE p DECIMALS 2. DATA zahl02 TYPE p DECIMALS 2. LIKE Dies hat allerdings den entscheidenden Nachteil, dass Sie immer selbst dafür sorgen müssen, die Deklaration von ZAHL02 nachzupflegen, falls sich die Deklaration von ZAHL01 ändert. Bei vielen abhängigen Deklarationen wird dies schnell zu einer sehr mühseligen und langatmigen Arbeit. Einfacher ist es, bei ZAHL02 auf die Deklaration von ZAHL01 zu verweisen. Dies geschieht mit dem Zusatz LIKE: DATA zahl01 TYPE p DECIMALS 2. DATA zahl02 LIKE zahl01. Damit ist gewährleistet, dass die Deklaration von ZAHL02 immer richtig bleibt, da sie so an die Deklaration von ZAHL01 geknüpft ist. Sollte einmal ein Anlass bestehen, die Zahl der Dezimalstellen beispielsweise von zwei auf vier zu erhöhen, muss nur die Deklaration von ZAHL01 geändert werden; die Deklaration von ZAHL02 wird automatisch angepasst. Natürlich gilt dies entsprechend für alle Variablen in einem Report, die auf die Deklaration von ZAHL01 verweisen. Inkonsistenzen vermeiden Auf diese Weise können Sie zwar erreichen, dass Inkonsistenzen innerhalb eines Reports vermieden werden, aber falls in verschiedenen Reports gleichlautende Deklarationen von Variablen benötigt 114 Felder deklarieren werden, müssen Sie sich bei der Deklaration beispielsweise auf ein Tabellenfeld im ABAP Dictionary beziehen. Möchten Sie im Report die Variable LAUFENDE_NUMMER genauso deklarieren wie das Feld TNUMMER der Tabelle ZTEILNEHMER, schreiben Sie: DATA laufende_nummer TYPE zteilnehmer-tnummer. Mit dieser Methode müssen Sie in den einzelnen Reports keine Anpassung dieser Variablen mehr vornehmen. Sollte sich je eine Änderung hinsichtlich der Länge ergeben, betrifft sie ausschließlich die Domäne des Tabellenfeldes. Alle betroffenen Reports werden automatisch beim ersten Start nach der Änderung nachgeneriert, und kein einziger Quellcode muss aus diesem Grund mehr geändert werden. Postleitzahlen Der Praxisbezug dieses Vorgehens wird schnell deutlich, wenn Sie sich daran erinnern, dass in der Bundesrepublik die Postleitzahlen früher vierstellig waren und im Jahr 1993 auf fünf Stellen umgestellt wurden. Teilweise mussten Entwickler in Hunderten kundenspezifischer Programme das Postleitzahlenfeld suchen und umstellen, die Programme wieder binden und kompilieren. Dies war eine absolut lästige Angelegenheit – man glaubt gar nicht, wie viele verschiedene Möglichkeiten es gibt, um das Wort »Postleitzahl« abzukürzen und eine Variable zu deklarieren! Mit unserer Methode wäre das Problem schnell gelöst gewesen. Ähnliche Probleme treten auf, wenn Unternehmen – beispielsweise bedingt durch eine Fusion – ihre Organisation erheblich umstellen und plötzlich das früher einstellige Regionskennzeichen nicht mehr ausreicht, um knapp fünfhundert Regionen zu unterscheiden, in denen das Unternehmen tätig ist. Oder, um zum Beispiel Postleitzahl zurückzukehren, das Unternehmen wird international tätig und muss neben rein numerischen Postleitzahlen auch englische Postleitzahlen verwalten, die Buchstaben enthalten. Für jeden Datentyp vergibt das System Initialwerte. Für die Datentypen i und p belegt das SAP-System das Feld zunächst mit dem Wert 0. Manchmal kann es jedoch sehr nützlich sein, eine Variable selbst mit einem Startwert zu versehen – hierzu verwenden Sie bei der DATA-Anweisung den Zusatz VALUE. Soll beispielsweise die Variable ZAHL01 eine ganze Zahl darstellen und mit dem Wert 5 vorbelegt werden, lautet die Anweisung: 115 VALUE 4.2 4 Felder und Berechnungen DATA zahl01 TYPE i VALUE 5. Bei einer Vorbelegung mit dem negativen Wert –105 müsste das negative Vorzeichen mitgeschrieben werden, und die Anweisung würde entsprechend lauten: DATA zahl01 TYPE i VALUE -105. Initialwerte mit Nachkommastellen Auch dies ist relativ einfach. Soll die Variable ZAHL01 hingegen eine Dezimalzahl mit zwei Nachkommastellen sein, wird das Ganze schon etwas aufwendiger. Lautet der Plan, die Variable ZAHL01 beispielsweise mit dem Wert 3,14 vorzubelegen, würde man eigentlich eine Anweisung vermuten wie: DATA zahl01 TYPE p DECIMALS 2 VALUE 3,14. Dies funktioniert aber leider nicht: Der Doppelpunkt nach DATA fehlt, und das Komma ist für einen Kettensatz und eine zweite Anweisung reserviert, in diesem Fall: DATA 14. Dies ergäbe leider auch keinen Sinn. Es funktioniert auch nicht, für das Dezimaltrennzeichen anstelle des Kommas einen Punkt einzusetzen. Grundsätzlich ist diese Idee ausgezeichnet, weil das System intern als Dezimaltrennzeichen tatsächlich einen Punkt verwendet, aber wie Sie wissen, ist der Punkt für das Ende einer Anweisung reserviert. Für das System würden dann zwei Anweisungen in einer Zeile stehen, wobei die zweite keinen Sinn ergibt. Lösung: Literal Deshalb ist es formal korrekt, wenn Sie den Vorbelegungswert in ein Literal schreiben: Grundrechenarten derten Inhalt, mit einer eigenen Anweisung namens CONSTANTS arbeiten. Damit werden wir denjenigen Fällen gerecht, in denen gewährleistet sein muss, dass ein Feldinhalt während der Laufzeit des Reports unverändert bleiben soll. Stoßen Sie in der Praxis auf ein solches Beispiel, ist die CONSTANTS-Anweisung geeigneter als die DATAAnweisung. Das System unterstützt dieses Konzept dadurch, dass bei Veränderungsversuchen dieser Felder Syntax- oder Laufzeitfehler generiert werden. Da diese Anweisungen allerdings bis auf den Verwendungszweck weitgehend identisch sind, verzichten wir für den Einstieg auf die CONSTANTS-Anweisung. Für einfache arithmetische Operationen könnten unsere Deklarationen deshalb vorerst so aussehen: DATA zahl01 TYPE p DECIMALS 2 VALUE '-4.56'. DATA zahl02 LIKE zahl01 VALUE '5.67'. DATA ergebnis LIKE zahl01. Die Variable ZAHL01 gibt den Datentyp p und die Anzahl von zwei Dezimalstellen vor. Außerdem wird der Variablen die negative Zahl – 4,56 als Startwert zugewiesen. Die Variable ZAHL02 verweist hinsichtlich des Typs und der Dezimalstellen auf die Variable ZAHL01 und erhält als Startwert die Zahl 5,67. Die Variable ERGEBNIS verweist hinsichtlich des Typs und der Dezimalstellen ebenfalls auf ZAHL01. Der Vorteil dieser Schreibweise besteht darin, dass bei einer Änderung der Deklaration nur die Deklaration von ZAHL01 geändert werden muss, die Deklarationen von ZAHL02 und ERGEBNIS werden automatisch angepasst. DATA zahl01 TYPE p DECIMALS 2 VALUE '3.14'. Bei der Vorbelegung mit der negativen Zahl –4,56 lautet die richtige Syntax entsprechend: DATA zahl01 TYPE p DECIMALS 2 VALUE '-4.56'. 4.2.2 CONSTANTS Konstanten deklarieren Der Vollständigkeit halber erwähnen wir hier, dass wir für die Deklaration von Konstanten, d. h. Feldern mit gleichbleibendem unverän- 116 4.3 Grundrechenarten Für die Addition, Subtraktion, Multiplikation und Division in ABAP haben wir damit bereits alle erforderlichen Variablen deklariert. Arithmetische Operationen können Sie nun leicht über Zuweisungen durchführen: Soll beispielsweise der Inhalt der Felder ZAHL01 und ZAHL02 addiert werden, schreiben Sie einfach: ergebnis = zahl01 + zahl02. 117 Einfache arithmetische Operationen 4.3 4 Felder und Berechnungen Mathematischer Ausdruck Formal ist anzumerken, dass rechts vom Gleichheitszeichen die arithmetische Operation selbst stehen muss. Das Ergebnis der Operation wird in das links vom Gleichheitszeichen stehende Feld eingetragen, die Felder ZAHL01 und ZAHL02 behalten auch nach der Berechnung ihren alten Inhalt. Anders hingegen verhält es sich mit dem Feld links vom Gleichheitszeichen: Im Feld ERGEBNIS steht nach der Berechnung nicht mehr der alte, sondern der neue Inhalt; der alte Inhalt des Feldes wurde ersetzt. Leerzeichen in arithmetischen Operationen Darüber hinaus ist für die richtige Schreibweise der Umgang mit Leerzeichen wichtig: Sie müssen sowohl vor als auch nach dem Gleichheitszeichen sowie vor und nach dem Rechenzeichen stehen, im oberen Beispiel dem Pluszeichen (+). Wenn Sie später einmal mit komplexeren Ausdrücken und mehreren Klammerebenen arbeiten, sollten Sie schon jetzt daran denken, dass in solchen Fällen auch vor und nach jeder Klammer ein Leerzeichen stehen muss. Dabei muss es jeweils mindestens ein Leerzeichen sein; die Eingabe mehrerer Leerzeichen schadet nicht weiter. Der Grund für diese Schreibkonvention liegt darin, dass es Funktionen gibt, die ohne Leerzeichen direkt an das Feld geschrieben werden. Damit das System nun unterscheiden kann, ob es sich um eine arithmetische Operation oder eine solche Funktion handelt, wird das Leerzeichen unbedingt benötigt. Mit Festwerten arbeiten Soll zum Inhalt der Variablen ZAHL02 ein Festwert, beispielsweise die Zahl 2, addiert werden, lautet die Anweisung: zahl02 = zahl01 + 2. Auch hier gilt die Regel, dass in der Variablen links vom Gleichheitszeichen der alte Inhalt durch den neuen ersetzt wird. Natürlich könnte man zum Inhalt derselben Variablen auch einen Festwert addieren, beispielsweise um einen Zähler um 1 zu erhöhen. Dann würde die Anweisung lauten: zahl01 = zahl01 + 1. Auch hier gilt wieder das gleiche Prinzip: Rechts vom Gleichheitszeichen wird der Wert der Operation bestimmt, d. h. der Inhalt von ZAHL01 und 1 werden addiert und das Ergebnis der Operation in die 118 Grundrechenarten 4.3 Variable links vom Gleichheitszeichen eingesetzt. Mit anderen Worten: ZAHL01 erhält einen neuen Inhalt. Für die Subtraktion, Multiplikation und Division lautet die Schreibweise entsprechend: ergebnis = zahl01 - zahl02. ergebnis = zahl01 * zahl02. ergebnis = zahl01 / zahl02. Als Rechenzeichen für Subtraktionen verwenden Sie das Minuszeichen (-), für Multiplikationen das Sternchen (*) und für Divisionen den Schrägstrich (/). Anstelle von Rechenzeichen könnten wir auch die Schlüsselwörter ADD, SUBTRACT, MULTIPLY und DIVIDE verwenden, die in der Praxis aber relativ selten anzutreffen sind; auch wir werden im Folgenden darauf verzichten. Anweisungen mit Schlüsselwort Damit haben Sie die Grundvoraussetzungen kennengelernt – und wir wenden uns den Details zu, denn hierin versteckt sich ja bekanntlich oft der Teufel. Beispielsweise haben nicht alle Felder die gleichen Attribute oder sind untereinander verträglich. 4.3.1 Kompatible und konvertible Datenobjekte Verfügen Felder über die gleichen Attribute, spricht man von kompatiblen Datenobjekten, d. h. dass diese Felder in allen technischen Eigenschaften (Typ, Feldlänge, Dezimalstellen) vollständig übereinstimmen. Sind die Attribute untereinander verträglich, spricht man von konvertiblen Datenobjekten. Dabei müssen die Datentypen konvertiert, d. h. umgewandelt werden; Voraussetzung hierfür sind entsprechende Konvertierungsregeln. Falls die Konvertierung nicht möglich ist, entstehen Syntax- oder Laufzeitfehler. Kompatible und konvertible Datenobjekte Beruhigend ist, dass im SAP-System bereits zahlreiche Konvertierungsregeln hinterlegt sind (siehe Abschnitt 4.3.2, »Konvertierungsregeln«). Das System wandelt bei entsprechenden Anweisungen nach diesen Regeln automatisch von einem Datentyp in einen anderen um. Sofern diese Regeln die von uns gewünschten Ergebnisse erzielen, haben wir kein Problem. Leider ist dies aber nicht immer der Fall, und leider existieren auch nicht für alle denkbaren Konstellationen Konvertierungsregeln. Automatische Umwandlung 119 4 Felder und Berechnungen Fehlerquellen Ganze und gepackte Zahlen sowie Exponentialzahlen Zähneknirschend muss außerdem hingenommen werden, dass für solche Fehler überwiegend die Entwickler selbst verantwortlich sind – denn es gibt z. B. keinen logischen Grund dafür, in einem Datumsfeld Sternchen und Sonderzeichen speichern zu wollen. Solche Syntax- oder Laufzeitfehler geschehen immer wieder einmal auch Fortgeschrittenen, und zwar insbesondere dann, wenn bereits bestehende Anwendungen modifiziert werden müssen. Auch bei einer Datenübernahme aus anderen Systemen tauchen solche Fehler auf – für einen Einsteiger erst einmal kein Grund zur Panik. Sollten beispielsweise ganze Zahlen, gepackte Zahlen und Exponentialzahlen in einer Operation vorkommen, würden die Exponentialzahlen den Datentyp auf höchster Ebene darstellen. Erst würden alle ganzen Zahlen in gepackte Zahlen umgewandelt, dann alle Zahlen in Exponentialzahlen, und schließlich würde die Operation mit Exponentialzahlen berechnet. Anschließend würde gemäß den Konvertierungsregeln der Wert der Exponentialzahlen in das Ergebnisfeld eingetragen. Sie können sich wahrscheinlich gut vorstellen, dass die Rechengenauigkeit schon durch den Datentyp des Ergebnisfeldes beeinflusst werden kann. 4.3.2 Was geschieht, wenn ... Dezimalzahl in ganze Zahl umwandeln Konvertierung verschiedener Datentypen Grundrechenarten Konvertierungsregeln Die Konvertierungsregeln legen fest, wie der Inhalt eines Quellfeldes in ein Zielfeld eingetragen wird. Quellfelder können verschiedene Datentypen haben, wie die bereits vorgestellten vom Typ p für gepackte und Typ i für ganze Zahlen. Da es, wie erwähnt, auch weitere Datentypen für Datums- und Zeitfelder oder Zeichenketten gibt, legen die Konvertierungsregeln pro Datentyp genau fest, wie der Inhalt des Quellfeldes in das Zielfeld eingestellt wird. Was geschieht, wenn Sie eine gepackte Zahl in ein Integerfeld stellen, was geschieht, wenn Sie eine gepackte Zahl zum Inhalt eines Datumsfeldes addieren, oder was geschieht, wenn Sie eine gepackte Zahl in ein Character-Feld schreiben? Lassen Sie uns hierzu eine Konvertierungsregel als Beispiel ansehen. Ist der Quelltyp ein Datenobjekt vom Typ p und der Zieltyp ein Datenobjekt vom Typ i (eine ganze Zahl), rundet das System die Dezimalstellen des Quellfeldes und stellt den Inhalt rechtsbündig in das Zielfeld. Ist das Zielfeld von seiner Länge her ausreichend, wird links mit Nullen aufgefüllt, anderenfalls kommt es zu einem Überlauf bzw. Laufzeitfehler. Stellen Sie beispielsweise die gepackte Zahl 4,44 in ein Integerfeld, hat ein Integerfeld danach den Inhalt 4; stellen Sie die gepackte Zahl 5,55 in ein Integerfeld, hat es den Inhalt 6. Falls in einer numerischen Operation mehrere verschiedene Datentypen vorkommen, konvertiert ABAP vor dem Ausführen der Operation alle Datentypen in den höchsten vorkommenden Datentyp, führt dann die Operation mit den konvertierten Werten aus und stellt anschließend das Ergebnis – eventuell wieder über eine Konvertierungsregel – in das Ergebnisfeld. 120 Um sich das Leben nicht zu erschweren, sollten Sie von Anfang an darauf achten, Ihre Datenobjekte möglichst kompatibel zu halten. Der Vollständigkeit halber erwähnen wir hier das COMPUTE-Schlüsselwort, das für numerische Operationen das ursprüngliche ABAP-Kommando ist. Die Schreibweise für eine Addition unter Zuhilfenahme des Schlüsselwortes COMPUTE lautet: COMPUTE ergebnis = zahl01 + zahl02. Wie Sie sehen, ist die Anweisung nur länger, und die Lesbarkeit wird nicht unbedingt erhöht. Glücklicherweise ist das Schlüsselwort COMPUTE optional und wird in der Praxis – außer für Recherchezwecke – kaum verwendet; die meisten Entwickler bevorzugen die verkürzte Schreibweise, die intern vom System exakt gleich behandelt wird, und auch wir arbeiten im Folgenden ohne das Schlüsselwort COMPUTE: ergebnis = zahl01 + zahl02. Gut zu wissen … Es gibt allerdings einen Fall, in dem es notwendig ist zu wissen, dass es die COMPUTE-Anweisung gibt: Falls Sie im System die Dokumentation zu selten benötigten Funktionen suchen, finden Sie diese nämlich nur bei der COMPUTE-Anweisung. Ab SAP NetWeaver 7.0 EHP 2 bzw. SAP NetWeaver 7.3 erlaubt die COMPUTE-Anweisung den Zusatz EXACT, was bei Berechnungen mit dezimalen Gleitpunktzahlen ein besonderes Verhalten bewirkt. Dieser Zusatz ist nur im Zusammenhang mit dem ausgeschriebenen Schlüsselwort COMPUTE verfügbar. 121 COMPUTE 4.3 4 Felder und Berechnungen 4.3.3 Verschiedene Fälle Besonderheiten bei der Division Für Berechnungen in ABAP stellen Addition, Subtraktion und Multiplikation kein weiteres Problem dar; nur die Division sollten wir uns noch etwas genauer ansehen. Es gibt Fälle, in denen Sie ein Divisionsergebnis mit Nachkommastellen wünschen, aber auch Fälle, in denen Sie ganzzahlig ohne Rest teilen möchten. Vielleicht interessiert uns aber auch nur der Rest einer solchen Division. Für diese verschiedenen Varianten gibt es in ABAP auch verschiedene Anweisungen. Der einfachste Fall einer Division wird – wie bereits erläutert – durch den Schrägstrich (/) dargestellt: DATA zahl01 TYPE p DECIMALS 2 VALUE '4.56'. DATA zahl02 LIKE zahl01 VALUE '5.67'. DATA ergebnis LIKE zahl01. ergebnis = zahl02 / zahl01. Rechengenauigkeit DIV Wenn Sie das Ergebnis mit dem Taschenrechner ausrechnen, erhalten Sie die Zahl 1,243421053. Wie verhält sich ABAP? Alle Variablen sind gleichlautend deklariert. Eine gepackte Zahl hat maximal 16 Bytes, dies bedeutet 32 Stellen, inklusive Vorzeichen. Das System würde das genaue Ergebnis liefern (bei ABAP liegt die Rechengenauigkeit von gepackten Zahlen bei maximal 14 Nachkommastellen), es aber auf zwei Nachkommastellen in der Zielvariable runden, die wir selbst mit zwei Dezimalstellen deklariert haben. Diese erhält, durch ABAP kaufmännisch gerundet, den Wert 1.24. Falls Sie das Ergebnis einer ganzzahligen Division erhalten möchten, müssten Sie die Anweisung umschreiben und statt des Schrägstrichs den Operator DIV einsetzen: ergebnis = zahl02 DIV zahl01. Unter sonst gleichen Voraussetzungen ergibt die ganzzahlige Division für den Quotienten den Wert 1. Da die Zielvariable zwei Dezimalstellen hat, steht dort nach dem Ausführen der Anweisung als Inhalt 1.00. MOD Im dritten Fall interessiert uns der Rest der Ganzzahldivision. Für diesen Fall verwenden wir den Operanden MOD, und die Anweisung lautet: ergebnis = zahl02 MOD zahl01. 122 Codebeispiel zu Feldern und Berechnungen Wieder unter der Annahme, dass alle übrigen Faktoren gleichbleiben, ergibt die ganzzahlige Division 1, Rest 1,11. Dieser Rest wird mit zwei Dezimalstellen in die Zielvariable übertragen, und sie erhält dementsprechend als Inhalt den Wert 1.11. 1,5 Stunden Möglicherweise fragen Sie sich jetzt, ob solche Berechnungen überhaupt praxisrelevant sind: Aber denken Sie nur daran, dass Stunden, Tage oder Jahre in vielen Systemen nicht in Stunden und Minuten erfasst werden, sondern mit Dezimalwerten wie »1,5 Stunden«. Um diese Dezimalwerte auf Stunden und Minuten umzurechnen, kommen Sie um die genannten Divisionsmöglichkeiten nicht herum. Weitere Beispiele finden Sie in Kapitel 5, »Modifikation von Zeichenketten«, und Kapitel 8, »Rechnen mit Datum und Zeit, Mengen und Währungen«. 4.4 Codebeispiel zu Feldern und Berechnungen Schauen wir uns die verschiedenen Berechnungsmöglichkeiten nun anhand unseres vorbereiteten Reports an: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 *&---------------------------------------------* *& Report Z_TEILNEHMERLISTE02 * *& * *&---------------------------------------------* *& * *& * *&---------------------------------------------* REPORT z_teilnehmerliste02 . * Variable deklarieren DATA zahl01 TYPE p DECIMALS 2 VALUE '4.56'. DATA zahl02 LIKE zahl01 VALUE '5.67'. DATA ergebnis_addition LIKE zahl01. DATA ergebnis_subtraktion LIKE zahl01. DATA ergebnis_multiplikation LIKE zahl01. DATA ergebnis_division_genau LIKE zahl01. DATA ergebnis_division_ganzzahl LIKE zahl01. DATA ergebnis_division_rest LIKE zahl01. 123 4.4 4 Felder und Berechnungen 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 * Verarbeitungsteil zahl01 = zahl01 + 1. zahl02 = zahl01 + 2. ergebnis_addition = zahl01 + zahl02. ergebnis_subtraktion = zahl01 - zahl02. ergebnis_multiplikation = zahl01 * zahl02. ergebnis_division_genau = zahl02 / zahl01. ergebnis_division_ganzzahl = zahl02 DIV zahl01. ergebnis_division_rest = zahl02 MOD zahl01. * Ausgabeteil WRITE: / 'zahl01', zahl01, / 'zahl02', zahl02, / 'ergebnis_addition:', ergebnis_addition, / 'ergebnis_subtraktion:', ergebnis_subtraktion, / 'ergebnis_multiplikation:', ergebnis_multiplikation, / 'ergebnis_division_genau:', ergebnis_division_genau, / 'ergebnis_division_ganzzahl:', ergebnis_division_ganzzahl, / 'ergebnis_division_rest:', ergebnis_division_rest. Listing 4.1 Report Z_TEILNEHMERLISTE02 Codebeispiel zu Feldern und Berechnungen Zeile 12 Die Variable ZAHL01 wird als gepackte Zahl mit zwei Nachkommastellen deklariert, und sie erhält als Startwert die Zahl 4,56. Zeile 13 Die Variable ZAHL02 erhält als Startwert die Zahl 5,67 und die gleichen Eigenschaften wie ZAHL01. Zeile 14 bis 19 Die Ergebnisfelder werden deklariert; für jedes Ergebnis wird ein eigenes Feld angelegt. Natürlich hätte man nur das Feld ERGEBNIS anlegen und immer wieder überschreiben können, aber es hängt von der Art der Weiterverarbeitung ab, ob man einen Feldinhalt später vielleicht wieder benötigt oder nicht – und Sie möchten gleich die verschiedenen Berechnungsergebnisse ausgeben. Nicht mit Variablen geizen Arbeitsspeicher und Hardware sind kein Argument mehr, um mit Variablen zu knausern, sondern Lesbarkeit und Transparenz sind heute die wesentlicheren Qualitätsfaktoren. Wenn es der Qualität dient, sollten Sie deshalb nicht mit Variablen geizen. Zeile 21 Der Verarbeitungsteil beginnt. Anmerkungen zum Quellcode Nach den Kommentarzeilen gliedert sich unser Report in drei Teile, die im Folgenden kurz beschrieben sind. Zeile 22 Der Wert des Feldes ZAHL01 wird um 1 erhöht. Vor der Anweisung war der Inhalt 4.56, danach ist er 5.56. Zeile 1 bis 8 Diese Zeilen werden vom System wieder automatisch als Kommentarzeilen generiert. Zeile 11 Der Quellcode wird in übersichtliche Abschnitte eingeteilt, die der Lesbarkeit dienen. In Listing 4.1 werden diese Abschnitte mit drei Kommentarzeilen gebildet: Variable deklarieren (Zeile 11 bis 19), Verarbeitungsteil (Zeile 21 bis 29) und Ausgabeteil (Zeile 31 bis 39). 124 4.4 Zeile 23 Das Feld ZAHL02 erhält den Inhalt aus der Addition von ZAHL01 und der Zahl 2. Der alte Inhalt von ZAHL02 war 5.67, der neue Inhalt ist 7.56. Zeile 24 Das Feld ERGEBNIS_ADDITION erhält das Ergebnis der Operation ZAHL01 plus ZAHL02, das ist 5.56 plus 7.56 und ergibt 13.12. 125 Frage der Weiterverarbeitung 4 Felder und Berechnungen Codebeispiel zu Feldern und Berechnungen 4.4 Zeile 25 Das Ergebnis der Subtraktion von ZAHL01 und ZAHL02 ist die negative Zahl 2. Sie wird im Ergebnisfeld ERGEBNIS_SUBTRAKTION als 2.00- dargestellt. Zeile 26 Da ZAHL01 inzwischen den Wert 5.56 und ZAHL02 den Wert 7.56 hat, lautet das Ergebnis der Multiplikation auf zwei Nachkommastellen gerundet 42.03. Zeile 27 Das Ergebnis der Division: 7.56 geteilt durch 5.56 ist gerundet 1.36 – und gleichzeitig der neue Inhalt von ERGEBNIS_DIVISION_GENAU. Zeile 28 Die ganzzahlige Division ergibt 1.00. Durch die Formatierung werden die eigentlich überflüssigen Dezimalstellen mitgezogen. Abbildung 4.6 Listbild zum Beispiel der Grundrechenarten Formal und logisch ist hier alles richtig – aber auch das Auge programmiert mit! Da hier die Literale am Zeilenanfang unterschiedlich lang sind, stehen die ausgegebenen Variablen an unterschiedlichen Spaltenpositionen und damit nicht spaltengerecht. Deshalb kümmern wir uns im letzten Schritt noch um die optische Spaltenaufteilung. Verbesserte Listaufbereitung Zeile 31 Dieses kleine Problem lösen Sie, indem Sie dem WRITE-Kommando bei der Ausgabe mitteilen, an welcher Position einer Zeile die Variable abgebildet werden soll. Möchten Sie die Variable ab Spalte 30 ausgeben, müssen Sie Zeile 32 von Listing 4.1 folgendermaßen ändern: Der Abschnitt für die Listerstellung beginnt. WRITE: / 'zahl01', 30 zahl01, Zeile 29 Der Rest der Ganzzahldivision beträgt 2.00. Dieser Wert wird in das Feld ERGEBNIS_DIVISION_REST übertragen. Zeile 32 bis 39 Die WRITE-Anweisung gibt in einer neuen Zeile in Spalte 1 ein Literal als Text aus und anschließend mit einer Leerstelle den Inhalt der Variablen. Die WRITE-Anweisung ist als Kettensatz geschrieben, hinter dem sich eigentlich 16 WRITE-Anweisungen verbergen. Hinter der Anweisung WRITE steht ein Doppelpunkt; die einzelnen Anweisungen sind durch Kommata getrennt, und nur die letzte Anweisung des Kettensatzes wird mit einem Punkt abgeschlossen. Ausgabe des Quellcodes Wenn Sie den Report wie eben editiert, gesichert, geprüft und aktiviert haben, können Sie ihn ausführen, und das Listbild sollte wie in Abbildung 4.6 aussehen. 126 Verbesserungswürdige Optik Vor die betreffende Variable schreiben Sie einfach die Spaltenposition der Druckzeile. Beachten Sie, dass zwischen Spaltenposition und Variable mindestens eine Leerstelle bestehen bleiben muss. Komplexe Listen Die restlichen relevanten Zeilen könnten Sie entsprechend editieren, indem Sie vor jede betroffene Variable die Ausgabeposition schreiben. Bei kurzen und überschaubaren Ausgaben ist dieses Vorgehen auch vertretbar. Sollte eine Liste allerdings aufwendiger und komplexer zusammengesetzt sein, könnten Sie es auch mit der nachfolgend beschriebenen Möglichkeit versuchen – ähnlich des Verweises bei den Datendeklarationen mit LIKE. 127 Felder einer Liste spaltengerecht ausgeben 4 Felder und Berechnungen UNDER Einen Verweis auf ein anderes Objekt können Sie auch bei der Druckposition verwenden, indem Sie einfach auf die Position einer anderen Variablen verweisen. Sollte sich die Position der führenden Variablen ändern, ziehen alle anderen referenzierenden Variablen automatisch nach. Hierzu wird beim WRITE-Kommando die Aufbereitungsoption UNDER verwendet. Editieren Sie die Zeilen 33 bis 39 wie folgt: 33 34 35 36 37 38 39 / 'zahl02', zahl02 UNDER zahl01, / 'ergebnis_addition:', ergebnis_addition UNDER zahl01, / 'ergebnis_subtraktion:', ergebnis_subtraktion UNDER zahl01, / 'ergebnis_multiplikation:', ergebnis_multiplikation UNDER zahl01, / 'ergebnis_division_genau:', ergebnis_division_genau UNDER zahl01, / 'ergebnis_division_ganzzahl:', ergebnis_division_ganzzahl UNDER zahl01, / 'ergebnis_division_rest:', ergebnis_division_rest UNDER zahl01. Nach dem Sichern, Prüfen, Aktivieren und Ausführen des Reports sollte das Listbild wie in Abbildung 4.7 aussehen. Abbildung 4.7 Listbild mit spaltengerechter Ausgabe 128
© Copyright 2024 ExpyDoc