Show TOC Anfang des Inhaltsbereichs

Tabellenzeilen in Schleifen bearbeiten  Dokument im Navigationsbaum lokalisieren

Mit der Anweisung LOOP können spezielle Schleifen über beliebige interne Tabellen ausgeführt werden:

LOOP AT itab result bedingung.
  anweisungsblock
ENDLOOP.

Die einzelnen Zeilen der Tabelle werden nacheinander gemäß der im Ausgabeverhalten result gemachten Angaben gelesen und können im Anweisungsblock der Kontrollstruktur LOOP - ENDLOOP verarbeitet werden. Die Schleifen können alle Zeilen der internen Tabelle umfassen oder es können Bedingungen zur Zeilenauswahl bedingung angegeben werden. Innerhalb einer Schleife ist eine Gruppenstufenverarbeitung möglich.

Die Reihenfolge, in der die Zeilen bearbeitet werden, hängt wie folgt von der Tabellenart ab:

·        Standard-Tabellen und sortierte Tabellen

Die Einträge werden gemäß des linearen Index bearbeitet. Innerhalb des Verarbeitungsblocks enthält sy-tabix den Index der aktuellen Zeile.

·        Hash-Tabellen

Die Einträge werden solange keine Sortierung stattfand in der Reihenfolge bearbeitet, in der sie in die Tabelle eingefügt wurden. Innerhalb des Verarbeitungsblocks enthält sy-tabix den Wert 0.

Mehrere LOOP-Schleifen sind schachtelbar. Das Systemfeld sy-tabix hat nach Verlassen der Schleife den gleichen Wert wie vor Beginn der Schleife. Nach der Anweisung ENDLOOP enthält das Systemfeld sy-subrc den Wert 0, wenn mindestens eine Zeile bearbeitet wurde, ansonsten den Wert 4.

Innerhalb einer Schleife dürfen keine ändernden Operationen mit der gesamten internen Tabelle durchgeführt werden. Dabei ist zu beachten, dass auch das Sichern einer globalen internen Tabelle mit der LOCAL-Anweisung in einer Prozedur eine ändernde Operation auf der gesamten internen Tabelle ist, da dabei der Inhalt der Tabelle ausgetauscht wird. Beim Aufruf von Prozeduren innerhalb von Schleifen sollte kontrolliert werden, ob nicht eine der Prozeduren die gesamte interne Tabelle ändert. Nach einer gesamten Änderung kann die Schleife nicht mehr richtig durchlaufen werden.

Werden innerhalb eines Schleifendurchgangs einzelne Zeilen eingefügt oder gelöscht, so wird dies wie folgt in den weiteren Schleifendurchläufen berücksichtigt:

·        Das Einfügen von Zeilen hinter der aktuellen Zeile, bewirkt, dass die neuen Zeilen in den nachfolgenden Schleifendurchgängen durchlaufen werden.

·        Das Löschen von Zeilen hinter der aktuellen Zeile, bewirkt, dass die gelöschten Zeilen in den nachfolgenden Schleifendurchgängen nicht mehr durchlaufen werden.

·        Das Einfügen von Zeilen vor oder auf der aktuellen Zeile, bewirkt, dass die internen Schleifenzähler entsprechend hoch gesetzt werden.

·        Das Löschen von Zeilen vor oder auf der aktuellen Zeile, bewirkt, dass die internen Schleifenzähler entsprechend herab gesetzt werden.

Angabe des Ausgabeverhaltens

Das Ausgabeverhalten spezifiziert, wie eine Tabellenzeile im Anweisungsblock der Schleife zur Verfügung steht.

Verwendung eines Arbeitsbereichs

Um in der Schleife den Inhalt der aktuellen Zeile in einen Arbeitsbereich zu lesen, gibt man das Ausgabeverhalten result wie folgt an:

LOOP AT itab INTO wa bedingung.

Der Inhalt der Tabellenzeilen muss in den Datentyp des Arbeitsbereichs wa konvertierbar sein. Bei jedem Schleifendurchlauf wird eine Zeile der Tabelle in den Arbeitsbereich kopiert. Das Ende der Schleife beeinflußt den Arbeitsbereich nicht, d.h. der Inhalt von wa nach ENDLOOP ist wie im letzten Schleifendurchgang. Wird die Schleife nicht durchlaufen, da die Tabelle leer ist oder keine Zeile die Bedingung cond erfüllt, wird der Arbeitsbereich nicht geändert.

Verwendung eines Feldsymbols

Um in der Schleife den Inhalt der aktuellen Zeile über ein Feldsymbol ansprechen zu können, gibt man das Ausgabeverhalten result wie folgt an:

LOOP AT itab ASSIGNING <fs> bedingung.

In jedem Schleifendurchgang zeigt das Feldsymbol <fs> auf die gelesene Tabellenzeile. Wenn der Zeilentyp strukturiert ist, empfiehlt es sich, das Feldsymbol bei der Deklaration entsprechend zu typisieren, damit auf die Komponenten der Zeilen zugegriffen werden kann. Falls eine statische Typisierung nicht möglich ist, muss für den Zugriff auf die Komponenten von Strukturen mit weiteren Feldsymbolen und der Möglichkeit Strukturen komponentenweise zuzuweisen gearbeitet werden.

Das Ende der Schleife beeinflußt das Feldsymbol nicht, d.h. ihm bleibt nach ENDLOOP die letzte gelesene Zeile zugewiesen. Wird die Schleife nicht durchlaufen, da die Tabelle leer ist oder keine Zeile die Bedingung cond erfüllt, wird dem Feldsymbol keine Zeile zugewiesen.

Mehr Informationen zur Zuweisung von Tabellenzeilen an Feldsymbole finden sich unter Zugriff über Feldsymbole.

Zeilenzuweisung unterdrücken

Wenn der Inhalt der Tabellenzeilen innerhalb des Anweisungsblocks nicht benötigt wird, kann die Zuweisung an einen Arbeitsbereich oder an ein Feldsymbol wie folgt unterdrückt werden:

LOOP AT itab TRANSPORTING NO FIELDS bedingung.

Diese Anweisung ist sinnvoll, um zum Beispiel bei Index-Tabellen die internen Indexe bestimmter Zeilen im Systemfeld sy-tabix zu finden oder bei beliebigen Tabellen die Anzahl von Zeilen festzustellen, die einer bestimmten Bedingung genügen.

Bedingungen angeben

Um nicht alle Zeilen einer internen Tabelle zu lesen, kann wie folgt eine Bedingung zur Zeilenauswahl angegeben werden:

LOOP AT itab result WHERE cond.

Es werden alle Zeilen bearbeitet, die den logischen Ausdruck conderfüllen. Der logische Ausdruck cond kann aus verschiedenen Vergleichen zusammengesetzt sein. In jedem einzelnen Vergleich muss der erste Operand eine Komponente der Zeilenstruktur sein. Falls die Tabellenzeilen nicht strukturiert sind, kann der erste Operand der Vergleiche auch die Pseudokomponente table_line sein. Ein Vergleich bezieht sich dann auf die gesamte Zeile.

Falls der Zeilentyp der internen Tabelle Objektreferenzvariablen als Komponenten comp enthält oder der gesamte Zeilentyp eine Referenzvariable ist, können die Attribute attr des Objekts, auf welches die jeweilige Referenz einer Zeile zeigt, über comp->attr bzw. table_line->attr als erstes Feld eines Vergleichs verwendet werden.

Gruppenstufenverarbeitung

Innerhalb einer LOOP-Schleife über ein interne Tabelle ist eine Gruppenstufenverarbeitung möglich. Gruppenstufen in einer internen Tabelle bedeuten, dass hintereinanderfolgende Zeilen anhand des Inhalts bestimmter Felder in Gruppen eingeteilt werden können.

Die Gruppeneinteilung interner Tabellen richtet sich statisch nach der Reihenfolge der Felder in der Zeilenstruktur. Das erste Feld legt die hierarchisch höchste Gruppenstufe fest und so weiter. Die Gruppenstufenhierarchie muss schon beim Anlegen der internen Tabelle bekannt sein.

Die Gruppierung von Zeilen zu Gruppenstufen ergibt sich dadurch, dass die interne Tabelle genau nach der Reihenfolge sortiert wird, die ihrem Aufbau entspricht, d.h. zuerst nach dem ersten Feld, dann nach dem zweiten Feld und so weiter. Tabellen, deren Tabellenschlüssel mit den ersten Feldern übereinstimmt sind also besonders gut für die Gruppenstufenverarbeitung geeignet.

Die folgende Abbildung verdeutlicht Gruppenstufen in einer sortierten Tabelle, wobei unterschiedliche Inhalte in den ersten drei Feldern durch verschiedene Farben angedeutet werden.

Diese Grafik wird im zugehörigen Text erklärt

Jeder Farbwechsel in einer Spalte bedeutet einen Gruppenstufenwechsel der entsprechenden Hierarchiestufe. Innerhalb der Anweisungsblöcke von LOOP-Schleifen kann mit der Gruppenstufen-Anweisung AT auf einen Gruppenstufenwechsel reagiert werden, um Anweisungen nur für die entsprechende Zeilen auszuführen. Damit können beispielsweise Summen von bestimmten Untermengen aller Zeilen mit der Anweisung SUM berechnet werden.

Die Gruppenstufen-Anweisung AT definiert innerhalb einer LOOP-Schleife einen Anweisungsblock, der durch ENDAT beendet wird:

AT level.
  anweisungsblock
ENDAT.

Es kann auf folgende Gruppenstufenwechsel reagiert werden:

level

Bedeutung

FIRST

erste Zeile der internen Tabelle

LAST

letzte Zeile der internen Tabelle

NEW f

Anfang einer Gruppe von Zeilen mit dem gleichen Inhalt im Feld f und in den Feldern links von f

END Of f

Ende einer Gruppe von Zeilen mit dem gleichen Inhalt im Feld f und in den Feldern links von f

Die Gruppenstufenanweisungen erlauben es auf Gruppenwechsel in internen Tabellen reagieren, anstatt sie selbst mit logischen Ausdrücken zu programmieren. In der LOOP-Schleife müssen die AT-ENDAT-Anweisungsblöcke genau der Gruppenstufenhierarchie entsprechend hintereinander angeordnet sein. Falls die interne Tabelle itab Felder der Namen f1, f2,.... hat und nach diesen Spalten sortiert ist, müssen die Gruppenstufenanweisungen in der Schleife wie folgt aufgebaut sein:

LOOP AT itab.
  AT FIRST.... ENDAT.
    AT NEW
f1....... ENDAT.
      AT NEW
f2....... ENDAT.
     .......
          Einzelsatzverarbeitung
     .......
      AT END OF
f2.... ENDAT.
    AT END OF
f1.... ENDAT.
  AT LAST..... ENDAT.
ENDLOOP.

Die innerste Hierarchiestufe Einzelsatzverarbeitungdient der Verarbeitung von Tabellenzeilen, die keinem Gruppenstufenwechsel entsprechen. Es müssen nicht alle Gruppenstufenanweisungen verwendet werden. Alle verwendeten müssen jedoch in der oben angegebenen Reihenfolge programmiert werden. Gruppenstufenanweisungen sollten nicht in Schleifen, die über WHERE (oder FROM, TO bei Index-Tabellen) in der LOOP-Anweisung eingeschränkt sind, verwendet werden, und die Tabelle sollte in der Schleife nicht modifiziert werden.

Wenn ein Gruppenstufenfeld f1, f2,.... erst zur Laufzeit bekannt ist, kann es dynamisch als (n1), (n2), … angegeben werden, wobei n1, n2,.... den Namen von f1, f2,.... enthält. Ist n1, n2,....  zur Laufzeit leer, wird das Gruppenwechselkriterium ignoriert. Die Gruppenstufenfelder f1, f2,.... können durch die Angabe von Offset und Länge weiter auf Teilfelder eingegrenzt werden.

Wenn mit einem Arbeitsbereich wa gearbeitet wird, enthält dieser im AT-ENDAT-Anweisungsblock nicht die aktuelle Tabellenzeile. Alle zeichenartigen Felder rechts vom aktuellen Gruppenschlüssel sind mit Sternen (*) gefüllt. Alle anderen Felder rechts vom aktuellen Gruppenschlüssel enthalten ihren Initialwert.

Innerhalb eines AT-ENDAT-Blocks können die Inhalte der numerischen Felder der entsprechenden Gruppenstufe mit folgender Anweisung berechnet werden:

SUM.

Diese Anweisung darf nur innerhalb einer LOOP-Schleife angegeben werden. Innerhalb eines AT-ENDAT-Blocks, werden die Summen der numerischen Felder aller Zeilen in der aktuellen Zeilengruppe berechnet und in die entsprechenden Felder des Arbeitsbereichs geschrieben. Außerhalb eines AT-ENDAT-Blocks (Einzelsatzverarbeitung) werden die Summen der numerischen Felder aller Zeilen der internen Tabelle in jedem Schleifendurchlauf berechnet und in die entsprechenden Felder des Arbeitsbereichs geschrieben. Die SUM-Anweisung ist also nur in AT-ENDAT-Blöcken sinnvoll.

Enthält die interne Tabelle eine geschachtelte Tabelle, kann die SUM-Anweisung nicht verwendet werden. Weiterhin kann die SUM-Anweisung nicht verwendet werden, wenn ein Feldsymbol statt eines Arbeitsbereichs in der LOOP-Anweisung verwendet wird.

Beispiel

REPORT demo_int_tables_at_1.

DATA: BEGIN OF line,
         col1(1) TYPE c,
         col2 TYPE i,
         col3 TYPE i,
      END OF line.

DATA itab LIKE HASHED TABLE OF line
          WITH UNIQUE KEY col1 col2.

line-col1 = 'A'.
DO 3 TIMES.
  line-col2 = sy-index.
  line-col3 = sy-index ** 2.
  INSERT line INTO TABLE itab.
ENDDO.

line-col1 = 'B'.
DO 3 TIMES.
  line-col2 = 2 * sy-index.
  line-col3 = ( 2 * sy-index ) ** 2.
  INSERT line INTO TABLE itab.
ENDDO.

SORT itab.

LOOP AT itab INTO line.
  WRITE: / line-col1, line-col2, line-col3.
  AT END OF col1.
    SUM.
    ULINE.
    WRITE: / line-col1, line-col2, line-col3.
    SKIP.
  ENDAT.
  AT LAST.
    SUM.
    ULINE.
    WRITE: / line-col1, line-col2, line-col3.
  
ENDAT.
ENDLOOP.

Die Listenausgabe ist:

A          1          1

A          2          4

A          3          9
________________________________

A          6         14

B          2          4

B          4         16

B          6         36
________________________________

B         12         56

________________________________

*         18         70

Es wird eine Hash-Tabelle itab angelegt, mit sechs Zeilen gefüllt und sortiert. In der LOOP - ENDLOOP-Schleife wird der Arbeitsbereich line verwendet und für jeden Schleifendurchlauf ausgegeben. Das erste Feld des Tabellenschlüssels col1 wird zur Gruppenstufenverarbeitung verwendet. Die Summe aller numerischer Felder wird immer berechnet, wenn sich der Inhalt von col1 ändert und einmal für die letzte Tabellenzeile.

Beispiel REPORT demo_int_tables_at_2.

DATA: BEGIN OF line,
        carrid   TYPE sbook-carrid,
        connid   TYPE sbook-connid,
        fldate   TYPE sbook-fldate,
        custtype TYPE sbook-custtype,
        class    TYPE sbook-class,
        bookid   TYPE sbook-bookid,
      END OF line.

DATA itab LIKE SORTED TABLE OF line WITH UNIQUE KEY table_line.

SELECT carrid connid fldate custtype class bookid
       FROM sbook INTO CORRESPONDING FIELDS OF TABLE itab.

LOOP AT itab INTO line.

  AT FIRST.
    WRITE / 'List of Bookings'.
    ULINE.
  ENDAT.

    AT NEW carrid.
      WRITE: / 'Carrid:', line-carrid.
    ENDAT.

      AT NEW connid.
        WRITE: / 'Connid:', line-connid.
      ENDAT.

        AT NEW fldate.
          WRITE: / 'Fldate:', line-fldate.
        ENDAT.

          AT NEW custtype.
            WRITE: / 'Custtype:', line-custtype.
          ENDAT.

               WRITE: / line-bookid, line-class.

            AT END OF class.
              
ULINE.
            ENDAT.

ENDLOOP.

In diesem etwas ausführlicherem Beispiel wird die sortierte interne Tabelle itab über die Open SQL-Anweisung SELECT  mit Daten aus der Datenbanktabelle SBOOK gefüllt. Die Reihenfolge der Spalten in der internen Tabelle definiert die Gruppenstufenhierarchie. Da der Tabellenschlüssel die gesamte Zeile ist, stimmt die Sortierreihenfolge mit der Gruppenstufenhierarchie überein. Die Anordnung der Gruppenstufenanweisungen in der LOOP - ENDLOOP-Schleife ist wichtig.

Die Listenausgabe ist in etwa:

List of Bookings
Carrid: AA
Connid: 0017
Fldate: 1998/11/22
Custtype: B
00063509 C
00063517 C
...
______________________________________________
00063532 F
00063535 F
...
______________________________________________
Custtype: P
00063653 C
00063654 C
...
______________________________________________
00063668 F
00063670 F
...
______________________________________________
Fldate: 1998/29/11
Custtype: B
00064120 C
00064121 C
...

und so weiter.

Indexangaben bei Schleifen

Bei der Anweisung LOOP, die Schleifen über beliebige Tabellen ausführt, können bei Index-Tabellen die zu lesenden Zeilen über Indexangaben eingeschränkt werden:

LOOP AT itab result [FROM n1] [TO n2] bedingung.
  
anweisungsblock
ENDLOOP.

Die Ausführung der Schleife erfolgt wie bei beliebigen internen Tabellen. Innerhalb des Verarbeitungsblocks enthält sy-tabix den Index der aktuellen Zeile.

Mit den Zusätzen FROM und TO können die Indizes n1 und n2 der ersten bzw. letzten zu lesenden Zeile angegeben werden. Mit FROM und TO wird tatsächlich die Anzahl der Zeilen eingeschränkt, die gelesen werden muss. Der WHERE-Zusatz in der Bedingung verhindert lediglich, dass die Ausgabe result bearbeitet wird. Bei WHERE müssen alle Zeilen gelesen werden. Um die Performance zu verbessern, sollten FROM und TO also soweit wie möglich eingesetzt werden. Es kann auch vorteilhaft sein, die Schleife unter bestimmten Bedingungen mit den Anweisungen CONTINUE oder EXIT abzukürzen oder zu beenden.

Beispiel

REPORT demo_int_tables_loop_ind.

DATA: BEGIN OF line,
         col1 TYPE i,
         col2 TYPE i,
      END OF line.

DATA itab LIKE SORTED TABLE OF line WITH UNIQUE KEY table_line.

DO 30 TIMES.
  line-col1 = sy-index.
  line-col2 = sy-index ** 2.
  APPEND line TO itab.
ENDDO.

LOOP AT itab INTO line FROM 10 TO 25 WHERE col2 > 400.
  WRITE: / sy-tabix, line-col2.
ENDLOOP.

Die Listenausgabe ist:

        21       441

        22       484

        23       529

        24       576

        25       625

Es wird eine sortierte Tabelle itab mit 30 Zeilen gefüllt. Die LOOP-Schleife liest nur die Zeilen mit Index zwischen 10 und 25. Weiterhin ist der Inhalt von col2 auf Werte größer als 400 eingeschränkt.

 

Ende des Inhaltsbereichs