[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] Hilfsvariablen mit LET-Ausdruck definieren

LET

  • Verwendung innerhalb von Operatoren NEW, VALUE, CONV, COND, SWITCH, REDUCE, FOR …
  • es konnen inplace Variablen oder Feldsymbole deklariert werden
  • Variablen, die im LET-Ausdruck definiert wurden k?nnen nur innerhalb des jeweiligen Scopes verwendet werden

Variante 1 (Variablendefinition, CONV)

* Carrier
PARAMETERS: p_carrid TYPE scarr-carrid DEFAULT 'LH'.

START-OF-SELECTION.

* Daten holen
  SELECT * FROM scarr INTO TABLE @DATA(it_carr).

  TRY.
* String zusammenbauen
      DATA(lv_carr_name) = CONV string(
* Hilfsvariablen per LET definieren
* ersten Carrier mit Carrid holen, kann Exception CX_SY_ITAB_LINE_NOT_FOUND werfen
                                        LET <c> = it_carr[ carrid = p_carrid ]
                                            dp  = |: |
* Hilfsvariablen verwenden
                                        IN
                                        |{ <c>-carrname }{ dp }{ <c>-url }| ).

      WRITE: / lv_carr_name.

* Exceptions abfangen
    CATCH cx_root INTO DATA(e_txt).
      WRITE: / e_txt->get_text( ).
  ENDTRY.

Variante 2 (Variablendefinition, COND)

DATA(lv_lang) = COND string(
* Hilfsvariablen per LET definieren
                             LET lang     = cl_abap_syst=>get_language( )
                                 lang_iso = cl_i18n_languages=>sap1_to_sap2( im_lang_sap1 = lang )
* Hilfsvariablen verwenden
                             IN
                             WHEN lang_iso = 'DE' THEN 'Deutsch'
                             WHEN lang_iso = 'EN' THEN 'Englisch'
                             ELSE 'andere Sprache'
                           ).

WRITE: / lv_lang.

Variante 3 (Tabelleneinträge, VALUE)

TYPES: BEGIN OF ty_s_adr,
         id   TYPE i,
         city TYPE string,
       END OF ty_s_adr.

TYPES: ty_it_adr TYPE STANDARD TABLE OF ty_s_adr WITH DEFAULT KEY.

TYPES: BEGIN OF ty_s_person,
         city_id  TYPE i,
         forename TYPE string,
         surename TYPE string,
         age      TYPE i,
       END OF ty_s_person.

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

* Städte
DATA(it_city) = VALUE ty_it_adr(
                                 ( id = 100 city = 'Berlin' )
                                 ( id = 101 city = 'Hamburg' )
                                 ( id = 102 city = 'M?nchen' )
                               ).

* Tabelle mit Personen
DATA(it_persons) = VALUE ty_it_persons(
                                        ( city_id = 100 forename = 'Udo'   surename = 'Lehmann' age = 35 )
                                        ( city_id = 101 forename = 'Erika' surename = 'Müller'  age = 63 )
                                        ( city_id = 102 forename = 'Heinz' surename = 'Schulze' age = 65 )
                                ).

DATA(it_csv) = VALUE stringtab(
* alle Namen durchgehen
                                 FOR <p> IN it_persons INDEX INTO idx
* Hilfsvariablen zusammensetzen
                                   LET name       = |{ <p>-surename }, { <p>-forename }|
                                       city       = it_city[ id = <p>-city_id ]-city
                                       age_string = COND string( WHEN <p>-age > 63 THEN 'Rentner' ELSE 'kein Rentner' )
                                       output     = |{ idx };{ name };{ city };{ age_string }|
* Hilfsvariablen verwenden
                                   IN
* neue Zeile zu Tabelle hinzufügen
                                   ( output )
                               ).

* Anzeige
cl_demo_output=>display( it_csv ).

Variante 4 (CONV)

DATA(lv_i) = CONV i( LET x = 1 IN x ).
WRITE: / lv_i.

Variante 5 (NEW)

DATA(lv_i) = NEW i( LET x = 1 IN x ).
WRITE: / lv_i->*.

[ABAP] Interne Tabellen: Schleifen mit FOR, THEN, WHILE, GROUPS, IN GROUP

Variante 1 (FOR … WHILE)

DATA(it_strings) = VALUE stringtab( ).

it_strings = VALUE #(
* For i = 1 To 10
                      FOR i = 1 WHILE i < 11
                      (
                        |{ i }|
                      )
                    ).

cl_demo_output=>display( it_strings ).

Variante 2 (FOR … WHILE mit Schrittweite)

                        
DATA(it_strings) = VALUE stringtab( ).

it_strings = VALUE #(
* For i = 1 To 10 Step 2
                      FOR i = 1 THEN i + 2 WHILE i < 11
                      (
                        |{ i }|
                      )
                    ).

cl_demo_output=>display( it_strings ).

Variante 3 (NESTED FOR)

                        
SELECT * FROM sflight INTO TABLE @DATA(it_sflight).
SELECT * FROM spfli INTO TABLE @DATA(it_spfli).

DATA(it_strings) = VALUE stringtab(
* alle Einträge aus sflight ab 01.01.2013
                                    FOR <f> IN it_sflight INDEX INTO idxf WHERE ( fldate >= '20130101' )
* alle Einträge aus spfli mit den Schlüsseln wie in der Ergebnismenge des vorherigen FOR
                                      FOR <c> IN it_spfli INDEX INTO idxc WHERE ( carrid = <f>-carrid AND connid = <f>-connid )
                                      (
* Ausgabe als Stringtab
                                        |{ idxf } \| { idxc } \| { <c>-carrid } \| { <c>-connid } \| { <c>-airpfrom }|
                                      )
                                  ).

cl_demo_output=>display( it_strings ).

Variante 4 (FOR GROUPS, FOR … IN GROUP)

TYPES: BEGIN OF ty_mat,
         matnr TYPE matnr,
         mtart TYPE mtart,
         price TYPE kbetr,
       END OF ty_mat.

TYPES: ty_it_mat TYPE HASHED TABLE OF ty_mat WITH UNIQUE KEY matnr
                                             WITH NON-UNIQUE SORTED KEY key_mtart COMPONENTS mtart.

TYPES: BEGIN OF ty_mat_sum,
         mtart TYPE mtart,
         count TYPE i,
         price TYPE kbetr,
       END OF ty_mat_sum.

TYPES: ty_it_mat_sum TYPE HASHED TABLE OF ty_mat_sum WITH UNIQUE KEY mtart.

* Tabelle mit Materialien
DATA(it_mat) = VALUE ty_it_mat(
                                ( matnr = '1' mtart = 'ROH'  price = '1.56' )
                                ( matnr = '2' mtart = 'ROH'  price = '2.00' )
                                ( matnr = '3' mtart = 'NLAG' price = '3.10' )
                                ( matnr = '4' mtart = 'NLAG' price = '0.40' )
                                ( matnr = '5' mtart = 'NLAG' price = '4.10' )
                                ( matnr = '6' mtart = 'HALB' price = '1.00' )
                                ( matnr = '7' mtart = 'HALB' price = '0.10' )
                              ).

* Tabelle gruppiert nach Materialarten ohne 'HALB' und summierten Preisen
DATA(it_mat_sum) = VALUE ty_it_mat_sum(
                                        FOR GROUPS grp OF <mtart> IN it_mat WHERE ( mtart NE 'HALB' ) GROUP BY ( mtart = <mtart>-mtart size = GROUP SIZE )
                                        (
                                          mtart = grp-mtart " Materialart der Gruppe
                                          count = grp-size  " Anz. Elemente der Gruppe
                                          price = REDUCE #( " Summe über die Elemente der akt. Gruppe bilden
                                                            INIT p = '0.00'
                                                            FOR <m> IN GROUP grp WHERE ( mtart = grp-mtart )
                                                            NEXT p = p + <m>-price
                                                          )
                                        )
                                      ).

cl_demo_output=>display( it_mat_sum ).

Links

[ABAP] REDUCE: Minimum / Maximum in einer internen Tabelle suchen

* Maximum
DATA(lv_max) = 100.

* Zufallszahlen 1 ... lv_max
DATA(o_rand_i) = cl_abap_random_int=>create( seed = cl_abap_random=>seed( ) min = 1 max = lv_max ).

TYPES: ty_it_rand TYPE STANDARD TABLE OF i WITH DEFAULT KEY.

* Tabelle mit Zufallswerten
DATA(it_rand) = VALUE ty_it_rand( FOR v = 1 WHILE v < 11
                                  ( o_rand_i->get_next( ) ) ).

* Datenausgabe
LOOP AT it_rand ASSIGNING FIELD-SYMBOL(<r>).
  WRITE: / sy-tabix, ':', <r>.
ENDLOOP.

* Minimumsuche
DATA(min) = REDUCE i( INIT m = lv_max
                      FOR <v> IN it_rand
                      NEXT m = COND #( WHEN <v> < m THEN <v> ELSE m ) ).

WRITE: / 'Min:', min.

* Maximumsuche
DATA(max) = REDUCE i( INIT m = 0
                      FOR <v> IN it_rand
                      NEXT m = COND #( WHEN <v> > m THEN <v> ELSE m ) ).

WRITE: / 'Max:', max.

[ABAP] REDUCE: Spaltensumme eines Feldes einer internen Tabelle berechnen

DATA: it_spfli TYPE STANDARD TABLE OF spfli.

* Daten holen
SELECT * FROM spfli INTO TABLE it_spfli.

* Daten ausgeben
LOOP AT it_spfli ASSIGNING FIELD-SYMBOL(<f>).
  WRITE: / <f>-carrid, <f>-connid, <f>-fltime.
ENDLOOP.

* Gesamtflugzeit berechnen (Summe)
DATA(lv_fltime_sum) = REDUCE spfli-fltime( INIT s = 0
                                           FOR <l> IN it_spfli
                                           NEXT s = s + <l>-fltime ).

* Gesamtflugzeit ausgeben
WRITE: / '--> Gesamtflugzeit:', lv_fltime_sum.

[ABAP] REDUCE: Anzahl bestimmter Datensätze in einer internen Tabelle zählen

DATA: it_spfli TYPE STANDARD TABLE OF spfli.

* Daten holen
SELECT * FROM spfli INTO TABLE it_spfli.

* Daten ausgeben
LOOP AT it_spfli ASSIGNING FIELD-SYMBOL(<fs_spfli>).
  WRITE: / <fs_spfli>-carrid, <fs_spfli>-connid, <fs_spfli>-airpfrom, <fs_spfli>-airpto.
ENDLOOP.

* Datensätze für 'LH' zählen
DATA(lv_cnt_lh) = REDUCE i( INIT x = 0
                            FOR <l> IN it_spfli WHERE ( carrid = 'LH' )
                            NEXT x = x + 1 ).

* Anzahl 'LH'-Flüge ausgeben
WRITE: / '--> Anzahl LH-Flüge:', lv_cnt_lh.

[ABAP] Interne Tabelle mit VALUE und FOR kopieren, Tabellenindex der Datensätze übertragen

TYPES: BEGIN OF ty_sflight,
         carrid TYPE sflight-carrid,
         connid TYPE sflight-connid,
       END OF ty_sflight.

TYPES: BEGIN OF ty_sflight_filter,
         index  TYPE i,
         carrid TYPE sflight-carrid,
         connid TYPE sflight-connid,
       END OF ty_sflight_filter.

DATA: it_sflight TYPE STANDARD TABLE OF ty_sflight.
DATA: it_sflight_filter TYPE STANDARD TABLE OF ty_sflight_filter.
DATA: o_salv TYPE REF TO cl_salv_table.

* nach carrid und connid gruppieren und die Preise pro Gruppe summieren
SELECT carrid, connid FROM sflight INTO TABLE @it_sflight.

* alle Datensätze mit 'LH' kopieren, Index der Quelle merken
it_sflight_filter = VALUE #( FOR l IN it_sflight INDEX INTO idx WHERE ( carrid = 'LH' )
                             ( index = idx
                               carrid = l-carrid
                               connid = l-connid ) ).

cl_salv_table=>factory( IMPORTING
                          r_salv_table   = o_salv
                        CHANGING
                          t_table        = it_sflight_filter ).

o_salv->display( ).

[ABAP] Tabelleninhalt einer internen Tabelle anhand eines Kriteriums selektieren und kopieren (FILTER, VALUE, FOR, WHERE)

Variante 1 (VALUE, FOR, WHERE) – explizite Feldangabe

* Standardtabelle mit sortiertem Schlüssel carr_city definieren
TYPES: ty_it_spfli TYPE STANDARD TABLE OF spfli WITH DEFAULT KEY.

DATA: it_spfli TYPE ty_it_spfli.
DATA: it_for_spfli TYPE ty_it_spfli.

START-OF-SELECTION.

  SELECT * INTO TABLE it_spfli FROM spfli.

* Tabelleninhalt für Einträge mit carrid = 'LH' selektieren
* und mittels VALUE und FOR kopieren
  it_for_spfli = VALUE #( FOR l IN it_spfli WHERE ( carrid = 'LH' )
                          ( mandt = l-mandt
                            carrid = l-carrid
                            connid = l-connid
                            countryfr = l-countryfr
                            cityfrom = l-cityfrom
                            airpfrom = l-airpfrom
                            countryto = l-countryto
                            cityto = l-cityto
                            airpto = l-airpto
                            fltime = l-fltime
                            deptime = l-deptime
                            arrtime = l-arrtime
                            distance = l-distance
                            distid = l-distid
                            fltype = l-fltype
                            period = l-period ) ).

  LOOP AT it_for_spfli ASSIGNING FIELD-SYMBOL(<fs_l>).
    WRITE: / <fs_l>-carrid, <fs_l>-cityfrom, <fs_l>-deptime.
  ENDLOOP.

Variante 2 (VALUE, FOR, WHERE) – alle Felder mit Variable

* Standardtabelle mit sortiertem Schlüssel carr_city definieren
TYPES: ty_it_spfli TYPE STANDARD TABLE OF spfli WITH DEFAULT KEY.

DATA: it_spfli TYPE ty_it_spfli.
DATA: it_for_spfli TYPE ty_it_spfli.

START-OF-SELECTION.

  SELECT * INTO TABLE it_spfli FROM spfli.

* Tabelleninhalt für Einträge mit carrid = 'LH' selektieren
* und mittels VALUE und FOR kopieren
* ( l ) -> komplette Zeile
  it_for_spfli = VALUE #( FOR l IN it_spfli WHERE ( carrid = 'LH' )
                          ( l ) ).

  LOOP AT it_for_spfli ASSIGNING FIELD-SYMBOL(<fs_l>).
    WRITE: / <fs_l>-carrid, <fs_l>-cityfrom, <fs_l>-deptime.
  ENDLOOP.

Variante 3 (VALUE, FOR, WHERE) – alle Felder mit Feldsymbol

* Standardtabelle mit sortiertem Schlüssel carr_city definieren
TYPES: ty_it_spfli TYPE STANDARD TABLE OF spfli WITH DEFAULT KEY.

DATA: it_spfli TYPE ty_it_spfli.
DATA: it_for_spfli TYPE ty_it_spfli.

START-OF-SELECTION.

  SELECT * INTO TABLE it_spfli FROM spfli.

* Tabelleninhalt für Einträge mit carrid = 'LH' selektieren
* und mittels VALUE und FOR kopieren
* ( l ) -> komplette Zeile
  it_for_spfli = VALUE #( FOR <fs> IN it_spfli WHERE ( carrid = 'LH' )
                          ( <fs> ) ).

  LOOP AT it_for_spfli ASSIGNING FIELD-SYMBOL(<fs_l>).
    WRITE: / <fs_l>-carrid, <fs_l>-cityfrom, <fs_l>-deptime.
  ENDLOOP.

Variante 4 (FILTER, KEY, WHERE)

* Standardtabellem mit sortiertem Schlüssel
TYPES: ty_it_spfli TYPE STANDARD TABLE OF spfli WITH NON-UNIQUE SORTED KEY carr_city COMPONENTS carrid cityfrom.

DATA: it_spfli TYPE ty_it_spfli.
DATA: it_filter_spfli TYPE ty_it_spfli.

START-OF-SELECTION.

  SELECT * INTO TABLE it_spfli FROM spfli.

* Tabelleninhalt für Einträge mit carrid = 'LH' mittels Filter selektieren und kopieren
* Daten sind anhand des Schlüssels vorsortiert
  it_filter_spfli = FILTER #( it_spfli USING KEY carr_city WHERE carrid = CONV #( 'LH' ) ).

  LOOP AT it_filter_spfli ASSIGNING FIELD-SYMBOL(<fs_l>).
    WRITE: / <fs_l>-carrid, <fs_l>-cityfrom, <fs_l>-deptime.
  ENDLOOP.