Programmieren mit SAP ABAP: Teil 3 – Erstellung eines ABAP-Programms zur Ausgabe von Datensätzen in Listenform

Im dritten Teil unserer Blogreihe “Programmieren mit SAP ABAP” erstellen wir ein ABAP-Programm zur Ausgabe von Datensätzen in Listenform.

Inhaltsverzeichnis

ABAP-Programm erstellen

Im zweiten Teil von “Programmieren mit SAP ABAP” wurde erklärt, wie Sie eine eigene Datenbanktabelle im ABAP Dictionary anlegen und diese mit Datensätzen füllen können. Sofern Sie dies durchgeführt haben, können Sie für die folgenden Übungen gerne mit dieser Tabelle weiterarbeiten.

Wir werden zu diesem Zweck unsere Tabelle ZBACKWAREN verwenden, die eine Reihe von Informationen zu den Produkten einer Bäckereikette enthält. Falls Sie erst an dieser Stelle in die Übungen einsteigen, können Sie auch die Tabelle SPFLI nutzen, die standardmäßig in SAP-Systemen hinterlegt ist. Es handelt sich dabei um eine Tabelle, die verschiedene Daten zu Flügen beinhaltet.

Die Bäckereikette aus dem oben genannten Fallbeispiel plant, ihr Sortiment entsprechend dem Wunsch vieler Kunden auf ausschließlich vegane Produkte umzustellen. Ein Teil der Produkte erfüllt dieses Kriterium bereits, die übrigen sollen durch neue vegane Alternativen ersetzt werden. Es soll im Folgenden ein ABAP-Programm erstellt werden, das eine Übersicht aller bisher nicht-veganen Produkte in Form einer Liste ausgibt. Für jedes Produkt sollen Produkt-ID, -bezeichnung und -kategorie angezeigt werden. Zusammengefasst muss das zu erstellende ABAP-Programm also drei Dinge können:

  1. Daten aus der Datenbanktabelle auslesen
  2. Dabei berücksichtigen, dass nur Daten gelesen werden sollen, die eine bestimmte Bedingung erfüllen (hier: nur nicht-vegane Produkte)
  3. Dem Nutzer die gefundenen Daten als Liste anzeigen

SELECT-Befehl: Datensätze aus Datenbanktabellen auswählen

Zum Auslesen von Daten aus Datenbanktabellen wird gemeinhin die Anweisung SELECT genutzt. Diese hat folgende Syntax:

SELECT <result>
INTO [table] <target>
FROM <source>
WHERE <condition>
GROUP BY <fields>
HAVING <cond>
ORDER BY <fields>
.

Für unseren Zweck sind nicht alle der obenstehenden Zeilen relevant, sondern erst einmal die oberen vier. Hier werden zunächst die gewünschten Spalten (<result>) aus der Datenbanktabelle (<source>) in ein Ziel-Datenobjekt (<target>) gelesen und dort gespeichert. Mit WHERE <condition> können weiterhin logische Bedingungen definiert werden, um die Ergebnismenge einzuschränken.
Die Datenbanktabelle, die als <source> verwendet werden soll, ist bereits bekannt: In unserem Fall ist dies die Tabelle ZBACKWAREN. Die Ergebnismenge <result> innerhalb einer SELECT-Anweisung kann unterschiedlich definiert werden:

  • SELECT * : liest alle Spalten/Felder und alle Zeilen/Datensätze einer Datenbanktabelle
  • SELECT SINGLE * : liest alle Spalten/Felder für genau eine Zeile/einen Datensatz einer Datenbanktabelle
  • SELECT spalte1 spalte2 … : liest die festgelegten Spalten/Felder für alle Zeilen/Datensätze einer Datenbanktabelle
  • SELECT SINGLE spalte1 spalte2 … : liest die festgelegten Spalten/Felder für genau eine Zeile/einen Datensatz einer Datenbanktabelle

In unserem Fall sollen alle Spalten/Felder der Tabelle zunächst für alle Zeilen/Datensätze selektiert und die Selektion anschließend mit Hilfe der WHERE-Anweisung eingeschränkt werden. Für SELECT <result> wird also SELECT * eingesetzt.
Das Zielobjekt <target> ist so festzulegen, dass es von seiner Struktur her mit der Ergebnismenge <result> kompatibel ist. Das heißt: Wenn Sie mit einer SELECT-Anweisung einzelne Felder aus einer Datenbanktabelle selektieren möchten, benötigen Sie als Zielobjekte ebenfalls einzelne Felder.

Wenn SELECT * genutzt wird, wird als Zielobjekt eine interne Tabelle von demselben Typ wie die verwendete Datenbanktabelle benötigt. Dies ist in unserer Übung der Fall. In den DATA-Teil des Programms sollte also eine entsprechende interne Tabelle zur Nutzung als <target> aufgenommen werden. Beispiel:

Deklaration einer internen Tabelle

Bisher sieht die SELECT-Anweisung folgendermaßen aus (der Zusatz TABLE vor der Ergebnismenge ist dann notwendig, wenn es sich bei letzterer um eine Tabelle handelt):

SELECT-Anweisung

Nun wird noch eine Bedingung hinzugefügt, um explizit alle nicht-veganen Produkte aus der Datenbanktabelle zu selektieren. Dazu suchen Sie aus ZBACKWAREN das Feld heraus, mit dem die Produkte als (nicht-)vegan gekennzeichnet werden, hier also das Feld „VEGAN“. In der Domäne für dieses Datenelement wurde ein entsprechender Wertebereich definiert: X = vegan, leeres Feld = nicht-vegan. Gesucht sind alle Tabelleneinträge, bei denen der Wert für dieses Feld ungleich X ist. Dies wird mithilfe eines WHERE-Statements folgendermaßen umgesetzt:

SELECT-Anweisung mit Bedingung

Anstatt des Ausdrucks <> lässt sich an dieser Stelle alternativ auch NE (not equal) verwenden. Beide stehen für den logischen Operator „ungleich“. Die folgende Tabelle bietet einen Überblick über die wichtigsten logischen Operatoren für Datenobjekte in ABAP:

Logischer Operator (Textform oder Symbol) Bedeutung
EQ oder = Equal / gleich
NE oder <> Not equal / ungleich
GT oder > Greater than / größer als
GE oder >= Greater equal / größer gleich
LT oder < Less than / kleiner als
LE oder <= Less equal / kleiner gleich

LOOP- und WRITE-Befehl zur Ausgabe von selektierten Datensätzen

Es wurden im letzten Schritt alle gewünschten Datensätze selektiert und in einem Zwischenspeicher, der internen Tabelle itab_zbackwaren, abgelegt. Noch sind die ausgewählten Daten jedoch für die Nutzer der Anwendung in keiner Weise sichtbar.

Im Folgenden sollen die selektierten Datensätze daher mithilfe eines WRITE-Statements sichtbar in Form einer Liste ausgegeben werden. Es ist allerdings nicht möglich, per WRITE direkt auf eine Tabelle zuzugreifen (etwa WRITE itab_zbackwaren). Die Tabelleneinträge müssen zunächst Zeile für Zeile nacheinander in eine sogenannte work area, eine Art interne Hilfsstruktur, gelesen werden. Die Inhalte der work area können dann problemlos mittels WRITE-Befehls ausgegeben werden.

Innerhalb der DATA-Anweisung ist also eine passende work area zu der internen Tabelle itab_zbackwaren zu definieren (passend im Sinne von: die work area weist denselben Strukturtyp auf wie die Tabelle). Dies könnte folgendermaßen aussehen:

Deklaration eines Arbeitsbereichs
Um die interne Tabelle zeilenweise in die entsprechende work area zu lesen, wird der LOOP-Befehl verwendet. Dessen Syntax lautet (verkürzt):

LOOP AT <itab>
INTO <wa>
<cond>.
ENDLOOP.

Für <itab> ist die interne Tabelle einzusetzen und für <wa> die work area als Zielstruktur. <cond> steht für eventuelle logische Bedingungen, die für den Tabellendurchlauf mit LOOP gelten sollen. Beispiel: Es sollen nur die ersten drei Zeilen/Einträge der Tabelle gelesen werden. In Ergänzung zur oben genannten verkürzten Syntax gibt es weitere Varianten und mögliche Bestandteile des LOOP-Befehls, die an dieser Stelle jedoch noch nicht relevant sind und daher hier nicht genannt werden.
In unserem Beispiel wäre der LOOP-Befehl im Anschluss an das SELECT-Statement wie folgt umzusetzen:

LOOP-Anweisung
Im ersten Durchlauf der LOOP-Schleife wird die erste Zeile der internen Tabelle itab_zbackwaren in die work area gelesen. Nach dem ersten ENDLOOP springt das Programm wieder zum LOOP AT und liest die zweite Zeile der internen Tabelle. Diese Schleife wiederholt sich so lange, bis alle Zeilen der internen Tabelle einmal gelesen wurden.

Jetzt ist lediglich noch der WRITE-Befehl einzubauen, mit dem die Tabellenzeilen der Listenausgabe hinzugefügt werden sollen. Da jede Zeile, die mittels LOOP-Befehls durchlaufen wird, auch Teil der Liste werden soll, muss das WRITE-Statement direkt nach dem Auslesen der jeweiligen Zeile und vor dem LOOP-Ende eingefügt werden. Befände es sich hinter dem ENDLOOP, so würde es nur die eine Tabellenzeile ausgeben, die zuletzt im LOOP gelesen wurde (diese entspricht der letzten Zeile der internen Tabelle). Möglich wäre folgende Umsetzung der WRITE-Anweisung:

LOOP-Anweisung
Sie sehen, dass innerhalb des WRITE-Befehls auch festgelegt wird, welche konkreten Spalten der internen Tabelle gelesen werden sollen. Ausgehend von der work area werden diese jeweils mithilfe eines Bindestrichs ausgewählt, zum Beispiel wa_zbackwaren-produktid für die Spalte der Produkt-ID.

Mitttels eines Schrägstrichs lässt sich ein Zeilenumbruch erzeugen, der zur Übersichtlichkeit der Liste beiträgt. Bei den Begriffen in Hochkommata (beispielsweise. ‘Produkt-ID:’) handelt es sich jeweils um die Beschreibungen der Felder, zu denen anschließend mit wa_zbackwaren-… die entsprechenden Inhalte/Einträge aufgerufen werden.

Der vollständige Code Ihres Programms sollte folgendermaßen aussehen:

Kompletter ABAP-Code

Speichern, prüfen und aktivieren Sie das Programm. Drücken Sie anschließend wahlweise die Taste F8 oder das Schraubzwingen-Symbol, um das Programm auszuführen.

Icons zum Speichern, Prüfen, Aktivieren und Ausführen eines Programms

Icons zum Speichern, Prüfen, Aktivieren und Ausführen eines Programms

Es sollte sich ungefähr das folgende Bild ergeben:

Listenausgabe der nicht-veganen Produkte

Listenausgabe der nicht-veganen Produkte

Sie haben erfolgreich ein ABAP-Programm programmiert und sind jetzt bereit für den nächsten Teil der Blogreihe “Programmieren mit SAP ABAP”. Im vierten Beitrag lernen Sie die Ausführung bestimmter Anweisungsblöcke im Quellcode an Bedingungen knüpfen.

Über den Autor

Franziska Georg, Consultant SAP HCM bei CONET
Microsoft 365 Developer bei CONET Solutions GmbH | Beiträge

Franziska Georg beschäftigt sich im Bereich Workplace Solutions mit der Entwicklung von Lösungsbausteinen im Rahmen von Microsoft 365. Standardprodukte wie SharePoint Online oder Microsoft Teams passt sie mit Hilfe der eigenentwickelten Komponenten so an, dass eine individuell zugeschnittene Arbeitsumgebung entsteht.

1 Antwort

  1. Cyrille sagt:

    Hallo Franziska,

    wird das Programm unter SE11 geschrieben oder verwenden wir eine andere Transaktion? Leider steht es nicht in dem Tutorial drin.

    Danke und viele Grüße
    Cyrille

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert