[ABAP] Verwendung der Pseudokomponente TABLE_LINE in internen Tabellen

* Tabelle ohne Zeilen-Struktur
DATA: it_vbeln TYPE STANDARD TABLE OF vbeln WITH DEFAULT KEY.

* Beispieldaten
it_vbeln = VALUE #( ( '1234567890' )
                    ( '2345678901' )
                    ( '3456789012' )
                  ).

* Zugriff auf einen Tabellenzeile über Pseudokomponente TABLE_LINE
* TABLE_LINE steht immer für die komplette Zeile einer internen Tabelle
DATA(lv_vbeln) = it_vbeln[ table_line = '2345678901' ].

* Datenausgabe
WRITE: / lv_vbeln.

[ABAP] REDUCE: Kosten (Wertetabelle) summieren und neue Summentabelle erzeugen

TYPES: BEGIN OF ty_s_kosten,
         k1 TYPE decfloat16,
         k2 TYPE decfloat16,
       END OF ty_s_kosten.

TYPES: ty_it_kosten TYPE STANDARD TABLE OF ty_s_kosten WITH EMPTY KEY.
TYPES: ty_it_sum TYPE STANDARD TABLE OF decfloat16 WITH EMPTY KEY.

DATA(it_kosten) = VALUE ty_it_kosten( ( k1 = '0.59' k2 = '1.48' )
                                      ( k1 = '1.28' k2 = '2.31' )
                                      ( k1 = '4.07' k2 = '2.35' ) ).

* Summen ausrechnen, neue Tabelle mit den Summen erstellen
DATA(it_sum) = REDUCE ty_it_sum(
* Initialwerte (leere Tabelle) für die Rückgabe (Typen bei REDUCE und VALUE müssen identisch sein)
                                 INIT sum = VALUE ty_it_sum( )
* alle Datensätze aus it_kosten
                                 FOR <k> IN it_kosten
* neue Elemente an it_sum anfügen, auf Basis der alten "sum"
                                 NEXT sum = VALUE #( BASE sum
                                                     ( <k>-k1 + <k>-k2 )
                                                   )
                               ).

* Ausgabe
cl_demo_output=>write_data( it_kosten ).
cl_demo_output=>write_data( it_sum ).
cl_demo_output=>display( ).

[ABAP] REDUCE: Fibonacci-Zahlen berechnen

* Stringtabelle erstellen
DATA(it_fib) = REDUCE stringtab(
* Initialwerte
                                 INIT ret = VALUE stringtab( ( |0| ) ( |1| ) )
                                      x TYPE string
                                      y TYPE string
* 100 Durchläufe
                                 FOR n = 1 WHILE n < 101
* letztes und vorletztes Element der Liste ermitteln
                                 NEXT x   = ret[ lines( ret ) ]
                                      y   = ret[ lines( ret ) - 1 ]
* addieren und an bestehende Liste anfügen
                                      ret = VALUE #( BASE ret
                                                     ( x + y )
                                                   )
                               ).

* Ausgabe
cl_demo_output=>display( it_fib ).

[ABAP] Interne Tabellen: Speicherung und Suche von Key-Value-Paaren mit Hilfe von tiefen Strukturen

* Typ für Eingabedaten (Key)
TYPES: BEGIN OF ty_in,
         key1 TYPE string,
         key2 TYPE string,
       END OF ty_in.

* Typ für Ausgabedaten (Value)
TYPES: BEGIN OF ty_out,
         vorname  TYPE string,
         nachname TYPE string,
       END OF ty_out.

* Zusammengesetzte Tabellenzeile (tiefe Struktur) für Key-Value-Paare
TYPES: BEGIN OF ty_s_line,
         in  TYPE ty_in,
         out TYPE ty_out,
       END OF ty_s_line.

* Tabellentyp für Speicherung von Key-Value-Paaren
TYPES: ty_it_data TYPE HASHED TABLE OF ty_s_line WITH UNIQUE KEY in-key1 in-key2.

* Testdaten
DATA(it_data) = VALUE ty_it_data( ( in-key1 = 'A1' in-key2 = 'A2' out-vorname = 'Hans'     out-nachname = 'Müller' )
                                  ( in-key1 = 'B1' in-key2 = 'B2' out-vorname = 'Ida'      out-nachname = 'Schulze' )
                                  ( in-key1 = 'C1' in-key2 = 'C2' out-vorname = 'Heinz'    out-nachname = 'Lehmann' )
                                  ( in-key1 = 'D1' in-key2 = 'D2' out-vorname = 'Marianne' out-nachname = 'Meier' )
                                ).

* Struktur mit Suchkriterium
DATA(lv_in) = VALUE ty_in( key1 = 'A1' key2 = 'A2' ).
* Rückgabestruktur
DATA(lv_out) = VALUE ty_out( ).

* Übergabe der Struktur mit den Key-Werten
IF line_exists( it_data[ in = lv_in ] ).
* wenn Key gefunden, dann Rückgabestruktur übergeben
  lv_out = it_data[ in = lv_in ]-out.
* Datenausgabe
  cl_demo_output=>display( lv_out ).
ELSE.
  WRITE: / 'Nichts gefunden.'.
ENDIF.

[ABAP] In internen Tabellen suchen

Variante 1 (Teilstrings in String suchen)

DATA(lv_string) = |ABAP_ABAP|.
DATA(lv_search) = |BA|.

FIND ALL OCCURRENCES OF lv_search
  IN lv_string
  IGNORING CASE             " case insensitive
  RESULTS DATA(it_results). " TYPE match_result_tab

IF sy-subrc = 0.
  LOOP AT it_results ASSIGNING FIELD-SYMBOL(<r>).
    WRITE: / substring( val = lv_string off = <r>-offset len = <r>-length ).
  ENDLOOP.
ENDIF.

Variante 2 (erstes Auftreten eines String in der Liste)

DATA(it_strings) = VALUE stringtab( ( |ACCESS=true| )
                                    ( |SERVER_NAME='myserver'| )
                                    ( |SERVER_TIMEOUT=600| )
                                    ( |TOKEN='auzt76wwhbud8w8hs8'| ) ).

* erstes Auftreten des Teilstrings 'SERVER_' ermitteln, case-sensitive Suche
FIND FIRST OCCURRENCE OF SUBSTRING 'SERVER_'
  IN TABLE it_strings
  RESPECTING CASE          " case-sensitive
  MATCH LINE DATA(idx)     " Index
  MATCH OFFSET DATA(off)   " Offset
  MATCH LENGTH DATA(len).  " Länge

IF sy-subrc = 0.
  WRITE: / off.
  WRITE: / len.
  WRITE: / it_strings[ idx ].
ENDIF.

Variante 3 (alle gefundenen Strings in der Liste)

DATA(it_strings) = VALUE stringtab( ( |ACCESS=true| )
                                    ( |SERVER_NAME='myserver'| )
                                    ( |SERVER_TIMEOUT=600| )
                                    ( |TOKEN='auzt76wwhbud8w8hs8'| ) ).

FIND ALL OCCURRENCES OF SUBSTRING 'SERVER_'
  IN TABLE it_strings
  RESPECTING CASE           " case-sensitive
  RESULTS DATA(it_results). " Ausgabetabelle

IF sy-subrc = 0.
  LOOP AT it_results ASSIGNING FIELD-SYMBOL(<r>).
    WRITE: / it_strings[ <r>-line ], <r>-offset, <r>-length.
  ENDLOOP.
ENDIF.

Variante 4 (RegEx: alle gefundenen Strings in der Liste)

DATA(it_strings) = VALUE stringtab( ( |ACCESS=true| )
                                    ( |SERVER_NAME='myserver'| )
                                    ( |SERVER_TIMEOUT=600| )
                                    ( |TOKEN='auzt76wwhbud8w8hs8'| ) ).

* Alle Auftreten der Suchbegriffe NAME und TIMEOUT
FIND ALL OCCURRENCES OF REGEX 'NAME|TIMEOUT'
  IN TABLE it_strings
  RESPECTING CASE           " case-sensitive
  RESULTS DATA(it_results). " Ausgabetabelle

IF sy-subrc = 0.
  LOOP AT it_results ASSIGNING FIELD-SYMBOL(<r>).
    WRITE: / it_strings[ <r>-line ], <r>-offset, <r>-length.
  ENDLOOP.
ENDIF.

Links

[ABAP] Interne Tabellen: OPTIONAL – Leere Datensätze bei Table Expressions

TYPES: BEGIN OF ty_person,
         name TYPE string,
         age  TYPE i,
       END OF ty_person.

TYPES: ty_it_persons TYPE STANDARD TABLE OF ty_person WITH DEFAULT KEY.

DATA(it_persons) = VALUE ty_it_persons(
                                        ( name = 'Hugo' age = 40 )
                                        ( name = 'Ede' age = 65 )
                                        ( name = 'Ina' age = 35 )
                                      ).

* Datensatz für Person 'Heiner' ist nicht vorhanden -> leeren Datensatz zurückgeben
DATA(lv_p) = VALUE #( it_persons[ name = 'Heiner' ] OPTIONAL ).

WRITE: / lv_p-name.
WRITE: / lv_p-age.

* Datensatz mit Index 4 ist nicht vorhanden -> leeren Wert zurückgeben
DATA(lv_age) = VALUE #( it_persons[ 4 ]-age OPTIONAL ).

WRITE: / lv_age.

[ABAP] Interne Tabellen: DEFAULT VALUE bei Table Expressions

TYPES: BEGIN OF ty_person,
         name TYPE string,
         age  TYPE i,
       END OF ty_person.

TYPES: ty_it_persons TYPE STANDARD TABLE OF ty_person WITH DEFAULT KEY.

DATA(it_persons) = VALUE ty_it_persons(
                                        ( name = 'Hugo' age = 40 )
                                        ( name = 'Ede' age = 65 )
                                        ( name = 'Ina' age = 35 )
                                      ).

* Datensatz für Person 'Heiner' ist nicht vorhanden -> Default Datensatz <empty> zurückgeben
DATA(lv_p) = VALUE #( it_persons[ name = 'Heiner' ] DEFAULT VALUE #( name = '<empty>' age = -1 ) ).

WRITE: / lv_p-name.
WRITE: / lv_p-age.

* Datensatz mit Index 5 ist nicht vorhanden -> Default Datensatz <empty> zurückgeben
DATA(lv_i) = VALUE #( it_persons[ 5 ] DEFAULT VALUE #( name = '<empty>' age = -1 ) ).

WRITE: / lv_i-name.
WRITE: / lv_i-age.

* Datensatz mit Index 4 ist nicht vorhanden -> Default Wert für age (-1) zurückgeben
DATA(lv_age) = VALUE #( it_persons[ 4 ]-age DEFAULT -1 ).

WRITE: / lv_age.

[ABAP] Interne Tabellen: Daten mit LINES OF anfügen / einfügen

DATA(it_s1) = VALUE stringtab( ( |1| ) ( |1| ) ( |1| ) ).
DATA(it_s2) = VALUE stringtab( ( |2| ) ( |2| ) ( |2| ) ).
DATA(it_s3) = VALUE stringtab( ( |3| ) ( |3| ) ( |3| ) ).
DATA(it_s4) = VALUE stringtab( ( |4| ) ( |4| ) ( |4| ) ).

* Zeilen von it_s2 und it_s3 in it_out einfügen
DATA(it_out) = VALUE stringtab( ( LINES OF it_s2 )
                                ( LINES OF it_s3 )
                              ).

* it_s1 an Stelle INDEX 1 in it_out einfügen
INSERT LINES OF it_s1 INTO it_out INDEX 1.

* it_s4 an Tabelle it_out anfügen
APPEND LINES OF it_s4 TO it_out.

cl_demo_output=>display( it_out ).

[ABAP] Index einer Zeile in einer internen Tabelle

* Index des Tabelleneintrags ermitteln
DATA(idx) = line_index( itab[ col = '123' ] ).

* bei Vorhandensein des Eintrags ist der Index > 0,
* es wird bei Nichtvorhandensein idx = 0 gesetzt und KEINE Exception geworfen
IF idx > 0.
* Zeile an der Indexposition mit Feldsymbol verknüpfen
  ASSIGN itab[ idx ] TO FIELD-SYMBOL(<f>).
  IF <f> IS ASSIGNED.
* hier irgendetwas mit dem Feldsymbol (Zeile) durchführen

  ENDIF.
ELSE.
* Eintrag nicht gefunden

ENDIF.