Der Loop-Befehl in ABAP mit Codebeispielen

Der Loop-Befehl ist der wichtigste Schleifenbefehl der ABAP-Programmiersprache. Er ist so wichtig wie der for-Befehl oder der Iterator in Java.


Der Loop-Befehl arbeitet auf einer internen Tabelle. Das heißt: du hast vorher Daten aus einer Datenbanktabelle in eine interne Tabellenvariable ausgelesen oder vielleicht hast du die interne Tabelle auch in deinem Programm selbst aufgebaut.

MIt dem Loop-Befehl kannst du nun jede Zeile der Tabelle nacheinander anschauen, bei Bedarf verändern oder mit den Daten irgend etwas anstellen.

Den Loop-Befehl gibt es in zwei Varianten:

LOOP AT lt_tabelle INTO ls_struktur

In diesem Fall wird die Tabelle durchgegangen und Zeile für Zeile nacheinander in eine Variable kopiert. Üblicherweise handelt es sich beim Typ dieser Variable dann um eine Struktur. (Einzige Ausnahme: die Tabelle hat nur eine einzige Spalte).

Data: ls_sflight TYPE ts_sflight.
LOOP AT lt_table INTO ls_sflight.
...
ENDLOOP.

Diese Variante findet man am häufigsten. Besser ist aber die andere Variante:

LOOP AT lt_tabelle ASSIGNING <fs_field_symbol>

Auch in diesem Fall wird die Tabelle zeilenweise durchgegangen. Allerdings erfolgt die Zuweisung der Zeile auf ein Field Symbol. Die Daten werden also nicht kopiert. Es wird nur eine Referenz gesetzt. Die Tabellenzeile und die Daten des Feldsymbols sind ein- und dieselben. Eine Änderung der Tabellenzeile ändert auch den Inhalt des Feldsymbols und anders herum wird eine Änderung im Feldsymbol auch direkt in der Tabelle durchgeführt. Das ist dann praktisch, wenn man in der Schleife auch die Tabelle ändern will.

FIELD-SYMBOLS: <fs_sflight> type ts_sflight.
    LOOP AT lt_sflight ASSIGNING <fs_sflight>.
      ...
      " Direktes Ändern der Tabelle!
      <fs_sflight>-fldate = sy-datum.
    ENDLOOP.

Die verwendeten Datendefinitionen

In den beiden obigen Beispielen habe ich Auszüge aus dem Flugdatenbeispiel der SAP verwendet:

TYPES: BEGIN OF ts_sflight,
         carrid TYPE sflight-carrid,
         connid TYPE sflight-connid,
         fldate TYPE sflight-fldate,
         price  TYPE sflight-price,
       END OF ts_sflight,
       tt_sflight TYPE STANDARD TABLE OF ts_sflight.

DATA: lt_sflight TYPE tt_sflight,
      ls_sflight TYPE ts_sflight.

Und da wir auch ein paar Daten in einer lokalen Tabelle brauchen, habe ich ein paar Zeilen aus SFLIGHT selektiert:

  SELECT carrid connid fldate price
    FROM sflight
    INTO TABLE lt_sflight
    UP TO 5 ROWS.

Tabelle ändern bei LOOP AT

Auch dann, wenn man LOOP AT into ls_struktur verwendet, kann man die zugrunde liegende Tabelle ändern. Der Trick ist dies Systemvariable sy-tabix, die uns sagt, welche Zeile der Tabelle sich gerade in ls_struktur befindet. Hier ein direktes Beispiel:

     LOOP AT lt_sflight INTO ls_sflight.

      " Modify the flight date to SY-DATUM based on the loop index
      lt_sflight[ sy-tabix ]-fldate = sy-datum.
    endloop.

Es geht aber auch etwas anders: erst ls_sflight ändern und dann ls_sflight in die Tabelle zurückschreiben:

LOOP AT lt_sflight INTO ls_sflight.

      " Modify the flight date to SY-DATUM
      ls_sflight-fldate = sy-datum.

      " Update the original table with the modified work area using sy-tabix
      MODIFY lt_sflight FROM ls_sflight INDEX sy-tabix TRANSPORTING fldate.

Modify ändert die Tabelle lt_sflight mit den Daten aus ls_sflight. Die Zeile wird über den tabix bestimmt. Man kann dann noch mit transporting die Felder angeben, die überhaupt nur übernommen werden sollen. Wenn alle Felder übernommen werden sollen, kann dert transporting-Zusatz auch entfallen.

Wie du siehst: es sind immer Klimmzüge, wenn du die Tabelle bei loop at … into ändern willst. Deutlich einfacher ist es, den Loop in ein Field Symbol zu füttern und direkt auf die Tabelle durchzugreifen.

Inline-Deklarationen bei LOOP AT

Seit einiger Zeit bietet ABAP es an, Variablen inline bei der ersten Verwendung zu deklarieren und dabei auch die Datentypen aus dem Kontext abzuleiten. Das ist auch hier möglich. Das sieht dann so aus:

LOOP AT lt_table INTO DATA(ls_sflight).

bzw.

LOOP AT lt_sflight ASSIGNING FIELD-SYMBOL(<fs_sflight>).

Die DATA-Anweisung bzw. die FIELD-SYMBOL-Deklaration steht also direkt beim LOOP-Befehl. Es ist in diesem Fall keine Typangabe nötig. ABAP erkennt den Typ anhand des Zeilentyps der internen Tabelle.

LOOP mit EXIT

In der LOOP-Schleife gibt es die Möglichkeit, die Schleife abzubrechen:

 LOOP AT lt_sflight INTO ls_sflight.
      IF ls_sflight-price > 1000.
        EXIT. " Exit the loop if a price is greater than 1000
      ENDIF.
      ....
ENDLOOP.

Das Programm wird dann unmittelbar nach dem LOOP mit dem nächsten Befehl fortgesetzt. Die anderen Schleifendurchläufe entfallen komplett.

LOOP mit CONTINUE.

In der LOOP-Schleife gibt es auch die Möglichkeit, Zeilen zu überspringen:

 LOOP AT lt_sflight INTO ls_sflight.
      ...
      " Skip records with a price less than or equal to 1000
      IF ls_sflight-price <= 1000.
        CONTINUE.
      ENDIF.
      ...
ENDLOOP.

Continue bedeutet, dass der aktuelle Schleifendurchlauf beendet wird. Es kommt der nächste Schleifendurchlauf für die nächste Tabellenzeile dran, sofern noch weitere Zeilen vorhanden sind.

Mit dem Continue-Befehl ist es also möglich, sich die Daten der Zeile zunächst einmal genauer anzusehen, sich zu beraten und dann zu entscheiden, dass die Zeile doch nicht bearbeitet werden muss.

Man kann denselben Effekt auch mit dem Check-Befehl erreichen:

CHECK ls_sflight-price > 1000.

Auch damit wird der aktuelle Schleifendurchlauf beendet. Allerdings rät der Style Guide „clean ABAP“ mittlerweile offiziell davon ab, CHECK innerhalb eines LOOPs zu verwenden.

Mehr ABAP-Tips findest du hier.

heiko

Dipl.-Ing. Heiko Evermann

Vorheriger Artikel