Bedingter Abbruch in ABAP: Die CHECK-Anweisung in LOOP, DO und FORM erklärt

kategorie
ABAP-Statements
Veröffentlicht
autor
Johannes

Die CHECK-Anweisung ist eine Kontrollanweisung in ABAP. Ihr Hauptzweck ist es, den Programmfluss bedingt zu steuern, und zwar spezifisch in den folgenden Kontexten:

  1. Innerhalb von Schleifen (DO, WHILE, LOOP AT ... ENDLOOP): CHECK prüft eine Bedingung. Ist die Bedingung * falsch*, wird der aktuelle Schleifendurchlauf sofort abgebrochen, und das Programm springt zum nächsten Durchlauf (ähnlich wie CONTINUE). Ist die Bedingung wahr, läuft die Verarbeitung nach dem CHECK normal weiter.
  2. Innerhalb von Unterprogrammen (FORM ... ENDFORM): CHECK prüft eine Bedingung. Ist die Bedingung falsch, wird das gesamte Unterprogramm (FORM) sofort verlassen, und die Kontrolle kehrt zum aufrufenden Programmteil zurück (ähnlich wie EXIT innerhalb eines FORM). Ist die Bedingung wahr, läuft die Verarbeitung im Unterprogramm nach dem CHECK normal weiter.

Wichtig: Die Verwendung von CHECK außerhalb dieser beiden Kontexte (Schleifen und FORMs) ist in der Regel nicht vorgesehen, führt zu Syntaxfehlern oder ist Teil obsoleter Praktiken. In modernen Methoden (METHOD...ENDMETHOD) wird CHECK nicht zum Verlassen der Methode verwendet (dafür nimmt man RETURN); innerhalb einer Methode funktioniert CHECK aber normal, wenn es innerhalb einer Schleife steht.

Syntax

Die Syntax ist sehr einfach gehalten:

CHECK <logischer_ausdruck>.
  • <logischer_ausdruck>: Dies ist ein beliebiger Ausdruck, der zu einem Wahrheitswert ausgewertet werden kann ( abap_true oder abap_false). Beispiele sind Vergleiche (a = b, c > 10), Prüfungen auf Initialwerte ( my_var IS NOT INITIAL), Funktionsaufrufe mit booleschem Rückgabewert oder einfach eine boolesche Variable.

Funktionsweise im Detail

Die Kernlogik von CHECK ist: Nur wenn die Bedingung wahr ist, wird fortgefahren.

CHECK <bedingung>. ist funktional äquivalent zu:

IF NOT <bedingung>.
" Innerhalb einer Schleife:
CONTINUE.
" Innerhalb eines FORM:
EXIT.
ENDIF.
" Code hier wird nur ausgeführt, wenn <bedingung> wahr war.

Diese “Weiter bei Wahr”-Logik kann manchmal als umgekehrt zur IF-Anweisung empfunden werden, wo man oft den ” Fehlerfall” zuerst behandelt (IF <fehlerbedingung> THEN ... ENDIF).

Beispiele

1. CHECK innerhalb einer LOOP AT-Schleife

Nur bestimmte Einträge einer Tabelle verarbeiten:

TYPES: BEGIN OF ty_order,
order_id TYPE i,
status TYPE c LENGTH 1, " N=New, P=Processed, E=Error
END OF ty_order.
DATA: lt_orders TYPE STANDARD TABLE OF ty_order,
ls_order TYPE ty_order.
APPEND VALUE #( order_id = 1 status = 'N' ) TO lt_orders.
APPEND VALUE #( order_id = 2 status = 'P' ) TO lt_orders.
APPEND VALUE #( order_id = 3 status = 'N' ) TO lt_orders.
APPEND VALUE #( order_id = 4 status = 'E' ) TO lt_orders.
WRITE: / 'Verarbeite neue Aufträge:'.
LOOP AT lt_orders INTO ls_order.
CHECK ls_order-status = 'N'. " Nur weitermachen, wenn Status 'N' (Neu) ist
" Folgender Code wird nur für Aufträge 1 und 3 ausgeführt
WRITE: / ' -> Verarbeite Auftrag:', ls_order-order_id.
" ... weitere Verarbeitung ...
ls_order-status = 'P'. " Status ändern (Beispiel)
MODIFY lt_orders FROM ls_order INDEX sy-tabix.
ENDLOOP.
WRITE: / 'Verarbeitung abgeschlossen.'.

Ausgabe:

Verarbeite neue Aufträge:
-> Verarbeite Auftrag: 1
-> Verarbeite Auftrag: 3
Verarbeitung abgeschlossen.

2. CHECK innerhalb einer DO-Schleife

Bestimmte Iterationen überspringen:

DO 5 TIMES.
WRITE: / 'DO-Schleife, Durchlauf:', sy-index.
CHECK sy-index MOD 2 = 1. " Nur weitermachen für ungerade Durchläufe (1, 3, 5)
WRITE: ' -> Ungerader Durchlauf wurde verarbeitet.'.
ENDDO.

Ausgabe:

DO-Schleife, Durchlauf: 1
-> Ungerader Durchlauf wurde verarbeitet.
DO-Schleife, Durchlauf: 2
DO-Schleife, Durchlauf: 3
-> Ungerader Durchlauf wurde verarbeitet.
DO-Schleife, Durchlauf: 4
DO-Schleife, Durchlauf: 5
-> Ungerader Durchlauf wurde verarbeitet.

3. CHECK innerhalb eines FORM-Unterprogramms

Das Unterprogramm bei ungültigen Parametern vorzeitig verlassen:

START-OF-SELECTION.
PERFORM calculate_discount USING iv_amount = 100 iv_cust_type = 'A'.
PERFORM calculate_discount USING iv_amount = 200 iv_cust_type = 'X'. " Ungültiger Typ
PERFORM calculate_discount USING iv_amount = -50 iv_cust_type = 'B'. " Ungültiger Betrag
FORM calculate_discount USING iv_amount TYPE p DECIMALS 2
iv_cust_type TYPE c LENGTH 1.
WRITE: / 'FORM aufgerufen mit Betrag:', iv_amount, 'Typ:', iv_cust_type.
" Eingabeprüfungen
CHECK iv_amount > 0. " Verlassen, wenn Betrag nicht positiv ist
CHECK iv_cust_type = 'A' OR
iv_cust_type = 'B'. " Verlassen, wenn Kundentyp ungültig ist
" --- Nur hier weiter, wenn alle CHECKS erfolgreich waren ---
DATA lv_discount TYPE p DECIMALS 2.
IF iv_cust_type = 'A'.
lv_discount = iv_amount * '0.1'. " 10%
ELSE. " Muss 'B' sein
lv_discount = iv_amount * '0.05'. " 5%
ENDIF.
WRITE: ' -> Rabatt berechnet:', lv_discount.
ENDFORM.

Ausgabe:

FORM aufgerufen mit Betrag: 100.00 Typ: A
-> Rabatt berechnet: 10.00
FORM aufgerufen mit Betrag: 200.00 Typ: X
FORM aufgerufen mit Betrag: -50.00 Typ: B

(Man sieht, dass bei Aufruf 2 und 3 die Verarbeitung nach dem fehlgeschlagenen CHECK nicht mehr stattfindet).

Abgrenzung zu CONTINUE, EXIT, RETURN

  • CONTINUE (in Schleifen): Springt immer zum nächsten Schleifendurchlauf.
  • EXIT (in Schleifen/FORMs): Verlässt immer die gesamte Schleife bzw. das FORM.
  • RETURN (in Methoden/Funktionsbausteinen): Verlässt immer die Methode/den Funktionsbaustein.
  • CHECK <bedingung>.: Ist bedingt. Nur wenn die Bedingung falsch ist, wird ein implizites CONTINUE (in Schleifen) oder EXIT (in FORMs) ausgeführt.

Wichtige Hinweise / Best Practice

  • Obwohl CHECK funktional korrekt ist, bevorzugen viele ABAP-Entwickler heute explizite IF-Konstrukte mit CONTINUE, EXIT oder RETURN.
    " Statt: CHECK <bedingung>.
    IF NOT <bedingung>.
    CONTINUE. " oder EXIT / RETURN
    ENDIF.
    Dies wird oft als lesbarer und die Absicht klarer ausdrückend empfunden, da die IF NOT-Logik direkter sein kann.
  • Das Verständnis von CHECK ist wichtig für die Wartung und Analyse von bestehendem Code, insbesondere älterem Code, der FORM-Routinen verwendet.