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:

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

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, daß 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:

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 muß 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, muß 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 <cond> erfüllen. Der logische Ausdruck <cond> kann aus verschiedenen Vergleichen zusammengesetzt sein. In jedem einzelnen Vergleich muß 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, daß 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 muß schon beim Anlegen der internen Tabelle bekannt sein.

Die Gruppierung von Zeilen zu Gruppenstufen ergibt sich dadurch, daß 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>, <f 2>,.... 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 <Einzelsatzverarbeitung> dient 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 <fi> erst zur Laufzeit bekannt ist, kann es dynamisch als (<n i>) angegeben werden, wobei <n i> den Namen von <f i> enthält. Ist <n i> zur Laufzeit leer, wird das Gruppenwechselkriterium ignoriert. Die Gruppenstufenfelder <f i > 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.

 

 

 

Ende des Inhaltsbereichs