Der FOR-Ausdruck ermöglicht Inline-Iteration innerhalb von Konstruktorausdrücken wie VALUE, REDUCE und NEW. Er ersetzt viele LOOP AT ... APPEND-Konstrukte durch kompakte, funktionale Syntax.
Syntax
1. FOR … IN (Tabelleniteration)
FOR <variable> IN <tabelle> [ INDEX INTO <index> ] [ WHERE ( <bedingung> ) ]2. FOR … UNTIL/WHILE (Bedingte Iteration)
FOR <variable> = <startwert> [ THEN <ausdruck> ] UNTIL <bedingung>FOR <variable> = <startwert> [ THEN <ausdruck> ] WHILE <bedingung>3. FOR GROUPS (Gruppierung)
FOR GROUPS <gruppe> OF <variable> IN <tabelle> GROUP BY <gruppierungsausdruck>Grundprinzip
FOR wird innerhalb von VALUE, REDUCE oder NEW verwendet:
" Tabelle aus anderer Tabelle erstellenDATA(lt_result) = VALUE ty_result_tab( FOR ls_source IN lt_source ( feld1 = ls_source-feld1 feld2 = ls_source-feld2 )).Beispiele
1. Einfache Tabellentransformation
TYPES: BEGIN OF ty_person, id TYPE i, name TYPE string, age TYPE i, END OF ty_person, ty_persons TYPE TABLE OF ty_person WITH EMPTY KEY.
TYPES: ty_names TYPE TABLE OF string WITH EMPTY KEY.
DATA: lt_persons TYPE ty_persons.
lt_persons = VALUE #( ( id = 1 name = 'Max' age = 30 ) ( id = 2 name = 'Anna' age = 25 ) ( id = 3 name = 'Peter' age = 35 )).
" Nur Namen extrahierenDATA(lt_names) = VALUE ty_names( FOR ls_person IN lt_persons ( ls_person-name )).
" Ergebnis: Max, Anna, Peter2. Vergleich: FOR vs. LOOP
" === KLASSISCH MIT LOOP ===DATA: lt_names_classic TYPE ty_names.
LOOP AT lt_persons INTO DATA(ls_p). APPEND ls_p-name TO lt_names_classic.ENDLOOP.
" === MODERN MIT FOR ===DATA(lt_names_modern) = VALUE ty_names( FOR ls_p IN lt_persons ( ls_p-name )).3. FOR mit WHERE (Filtern)
" Nur Erwachsene (age >= 18)DATA(lt_adults) = VALUE ty_persons( FOR ls_person IN lt_persons WHERE ( age >= 18 ) ( ls_person )).
" Komplexere BedingungDATA(lt_filtered) = VALUE ty_persons( FOR ls_person IN lt_persons WHERE ( age >= 25 AND name <> 'Max' ) ( ls_person )).4. Transformation mit Berechnung
TYPES: BEGIN OF ty_product, id TYPE i, name TYPE string, price TYPE p DECIMALS 2, quantity TYPE i, END OF ty_product.
TYPES: BEGIN OF ty_order_line, product_id TYPE i, total TYPE p DECIMALS 2, END OF ty_order_line, ty_order_lines TYPE TABLE OF ty_order_line WITH EMPTY KEY.
DATA: lt_products TYPE TABLE OF ty_product.
lt_products = VALUE #( ( id = 1 name = 'Widget' price = '10.00' quantity = 5 ) ( id = 2 name = 'Gadget' price = '25.00' quantity = 3 ) ( id = 3 name = 'Gizmo' price = '15.00' quantity = 8 )).
" Bestellpositionen mit Gesamtpreis berechnenDATA(lt_order_lines) = VALUE ty_order_lines( FOR ls_prod IN lt_products ( product_id = ls_prod-id total = ls_prod-price * ls_prod-quantity )).5. INDEX INTO – Zeilenindex mitlesen
TYPES: BEGIN OF ty_numbered, position TYPE i, name TYPE string, END OF ty_numbered, ty_numbered_tab TYPE TABLE OF ty_numbered WITH EMPTY KEY.
DATA(lt_numbered) = VALUE ty_numbered_tab( FOR ls_person IN lt_persons INDEX INTO lv_idx ( position = lv_idx name = ls_person-name )).
" Ergebnis:" position = 1, name = 'Max'" position = 2, name = 'Anna'" position = 3, name = 'Peter'6. Verschachtelte FOR (Kartesisches Produkt)
TYPES: ty_colors TYPE TABLE OF string WITH EMPTY KEY, ty_sizes TYPE TABLE OF string WITH EMPTY KEY.
TYPES: BEGIN OF ty_variant, color TYPE string, size TYPE string, END OF ty_variant, ty_variants TYPE TABLE OF ty_variant WITH EMPTY KEY.
DATA: lt_colors TYPE ty_colors, lt_sizes TYPE ty_sizes.
lt_colors = VALUE #( ( `Rot` ) ( `Blau` ) ( `Grün` ) ).lt_sizes = VALUE #( ( `S` ) ( `M` ) ( `L` ) ).
" Alle Kombinationen erstellenDATA(lt_variants) = VALUE ty_variants( FOR lv_color IN lt_colors FOR lv_size IN lt_sizes ( color = lv_color size = lv_size )).
" Ergebnis: 9 Kombinationen (3x3)" Rot-S, Rot-M, Rot-L, Blau-S, Blau-M, ...7. FOR … UNTIL (Bedingte Iteration)
TYPES: ty_numbers TYPE TABLE OF i WITH EMPTY KEY.
" Zahlen 1 bis 10 generierenDATA(lt_1_to_10) = VALUE ty_numbers( FOR i = 1 UNTIL i > 10 ( i )).
" Mit THEN für SchrittweiteDATA(lt_even) = VALUE ty_numbers( FOR i = 2 THEN i + 2 UNTIL i > 20 ( i ))." Ergebnis: 2, 4, 6, 8, 10, 12, 14, 16, 18, 208. FOR … WHILE
" Quadratzahlen unter 100DATA(lt_squares) = VALUE ty_numbers( FOR n = 1 WHILE n * n < 100 ( n * n ))." Ergebnis: 1, 4, 9, 16, 25, 36, 49, 64, 819. FOR GROUPS – Gruppierung
TYPES: BEGIN OF ty_sale, region TYPE string, amount TYPE p DECIMALS 2, END OF ty_sale, ty_sales TYPE TABLE OF ty_sale WITH EMPTY KEY.
DATA: lt_sales TYPE ty_sales.
lt_sales = VALUE #( ( region = 'NORTH' amount = '1000.00' ) ( region = 'SOUTH' amount = '2000.00' ) ( region = 'NORTH' amount = '1500.00' ) ( region = 'EAST' amount = '800.00' ) ( region = 'SOUTH' amount = '1200.00' )).
TYPES: BEGIN OF ty_region_total, region TYPE string, total TYPE p DECIMALS 2, END OF ty_region_total, ty_region_totals TYPE TABLE OF ty_region_total WITH EMPTY KEY.
" Summe pro RegionDATA(lt_by_region) = VALUE ty_region_totals( FOR GROUPS <group> OF ls_sale IN lt_sales GROUP BY ls_sale-region ( region = <group> total = REDUCE p DECIMALS 2( INIT sum = CONV p DECIMALS 2( 0 ) FOR m IN GROUP <group> NEXT sum = sum + m-amount ) )).
" Ergebnis:" NORTH: 2500.00" SOUTH: 3200.00" EAST: 800.0010. FOR GROUPS mit mehreren Gruppierungsfeldern
TYPES: BEGIN OF ty_order, year TYPE i, month TYPE i, category TYPE string, amount TYPE p DECIMALS 2, END OF ty_order.
DATA: lt_orders TYPE TABLE OF ty_order.
lt_orders = VALUE #( ( year = 2024 month = 1 category = 'A' amount = 100 ) ( year = 2024 month = 1 category = 'A' amount = 150 ) ( year = 2024 month = 1 category = 'B' amount = 200 ) ( year = 2024 month = 2 category = 'A' amount = 300 )).
TYPES: BEGIN OF ty_group_key, year TYPE i, month TYPE i, END OF ty_group_key.
" Gruppierung nach Jahr und MonatDATA(lt_monthly) = VALUE ty_region_totals( FOR GROUPS <grp> OF ls_ord IN lt_orders GROUP BY ( year = ls_ord-year month = ls_ord-month ) ( region = |{ <grp>-year }/{ <grp>-month }| total = REDUCE p DECIMALS 2( INIT s = CONV p DECIMALS 2( 0 ) FOR m IN GROUP <grp> NEXT s = s + m-amount ) )).11. LET für lokale Variablen
TYPES: BEGIN OF ty_display, id TYPE i, display TYPE string, END OF ty_display, ty_displays TYPE TABLE OF ty_display WITH EMPTY KEY.
DATA(lt_display) = VALUE ty_displays( FOR ls_person IN lt_persons LET prefix = 'ID: ' suffix = COND #( WHEN ls_person-age >= 30 THEN ' (Senior)' ELSE '' ) IN ( id = ls_person-id display = |{ prefix }{ ls_person-id } - { ls_person-name }{ suffix }| )).12. FOR in REDUCE
" Summe aller BeträgeDATA(lv_total) = REDUCE p DECIMALS 2( INIT sum = CONV p DECIMALS 2( 0 ) FOR ls_sale IN lt_sales NEXT sum = sum + ls_sale-amount).
" Mit WHERE filternDATA(lv_north_total) = REDUCE p DECIMALS 2( INIT sum = CONV p DECIMALS 2( 0 ) FOR ls_sale IN lt_sales WHERE ( region = 'NORTH' ) NEXT sum = sum + ls_sale-amount).13. FOR in NEW (Datenreferenzen)
" Tabelle als Referenz erstellenDATA(lr_names) = NEW ty_names( FOR ls_person IN lt_persons ( ls_person-name )).
LOOP AT lr_names->* INTO DATA(lv_name). WRITE: / lv_name.ENDLOOP.14. Bestehendes erweitern (BASE)
DATA: lt_existing TYPE ty_names.
lt_existing = VALUE #( ( `Existing1` ) ( `Existing2` ) ).
" Neue Einträge hinzufügenDATA(lt_combined) = VALUE ty_names( BASE lt_existing FOR ls_person IN lt_persons ( ls_person-name )).
" Ergebnis: Existing1, Existing2, Max, Anna, Peter15. Komplexe Transformation mit CORRESPONDING
TYPES: BEGIN OF ty_source, kunnr TYPE string, name1 TYPE string, ort01 TYPE string, END OF ty_source,
BEGIN OF ty_target, customer_id TYPE string, customer_name TYPE string, city TYPE string, END OF ty_target, ty_targets TYPE TABLE OF ty_target WITH EMPTY KEY.
DATA: lt_source TYPE TABLE OF ty_source.
lt_source = VALUE #( ( kunnr = '1000' name1 = 'Müller GmbH' ort01 = 'Berlin' ) ( kunnr = '2000' name1 = 'Schmidt AG' ort01 = 'München' )).
" Transformation mit CORRESPONDINGDATA(lt_target) = VALUE ty_targets( FOR ls_src IN lt_source ( CORRESPONDING #( ls_src MAPPING customer_id = kunnr customer_name = name1 city = ort01 ) )).FOR-Varianten im Überblick
| Variante | Verwendung |
|---|---|
FOR var IN itab | Iteration über interne Tabelle |
FOR var IN itab WHERE (...) | Gefilterte Iteration |
FOR var IN itab INDEX INTO idx | Mit Zeilenindex |
FOR i = 1 UNTIL i > n | Zähler-Iteration (aufwärts) |
FOR i = n THEN i - 1 UNTIL i < 1 | Zähler-Iteration (abwärts) |
FOR i = 1 WHILE cond | Bedingte Iteration |
FOR GROUPS grp OF var IN itab GROUP BY ... | Gruppierung |
Kombinationen
" FOR in VALUEDATA(lt_result) = VALUE ty_tab( FOR ... ( ... ) ).
" FOR in REDUCEDATA(lv_result) = REDUCE type( INIT ... FOR ... NEXT ... ).
" FOR in NEWDATA(lr_result) = NEW ty_tab( FOR ... ( ... ) ).
" Verschachtelte FORDATA(lt_matrix) = VALUE ty_tab( FOR i = 1 UNTIL i > 3 FOR j = 1 UNTIL j > 3 ( row = i col = j )).Wichtige Hinweise / Best Practice
FORist nur innerhalb vonVALUE,REDUCE,NEWverwendbar – nicht standalone.- WHERE filtert effizienter als nachträgliches
IFim Rumpf. - INDEX INTO liefert den aktuellen Zeilenindex (1-basiert).
- Verschachtelte
FORerzeugen kartesische Produkte – Vorsicht bei großen Tabellen! FOR GROUPSist mächtig für Aggregationen nach Gruppierungsfeldern.LETermöglicht lokale Hilfsvariablen innerhalb des FOR-Ausdrucks.BASEerhält bestehende Tabelleneinträge beim Aufbau.- Kombinieren Sie mit
CORRESPONDINGfür Strukturtransformationen. FOR ... UNTIL/WHILEfür Iterationen ohne Quelltabelle (Zahlenreihen etc.).- Bei komplexer Logik kann ein
LOOP ATlesbarer sein.