[ABAP] Wichtige Systemvariablen mit der ABAP Systemklasse auslesen

* Alias User
WRITE: / cl_abap_syst=>get_alias_user( ).
* Mandant
WRITE: / cl_abap_syst=>get_client( ).
* Programmname
WRITE: / cl_abap_syst=>get_current_program( ).
* Applikationsserver
WRITE: / cl_abap_syst=>get_host_name( ).
* Instanz
WRITE: / cl_abap_syst=>get_instance_name( ).
* akt. Sprachenschlüssel
WRITE: / cl_abap_syst=>get_language( ).
* Anmeldesprache
WRITE: / cl_abap_syst=>get_logon_language( ).
* Session Anmeldestatus
CASE cl_abap_syst=>get_session_authentication( ).
  WHEN cl_abap_syst=>session_authenticated_user.
    WRITE: / 'Session läuft unter Benutzerkennung (nach Anmeldung).'.
  WHEN cl_abap_syst=>session_configured_identity.
    WRITE: / 'Session läuft unter (technischer) Servicebenutzer-Kennung.'.
  WHEN cl_abap_syst=>session_system_account.
    WRITE: / 'Session läuft unter Systemkennung (keine Anmeldung erfolgt).'.
  WHEN OTHERS.
    WRITE: / 'Session läuft unter unbekanntem Kontext.'.
ENDCASE.
* Transaktionscode
WRITE: / cl_abap_syst=>get_transaction_code( ).
* User
WRITE: / cl_abap_syst=>get_user_name( ).

[ABAP] Wertebereich einer Domäne auslesen

Variante 1 (get_ddic_fixed_values)

CLASS lcl_domvalues DEFINITION.
  PUBLIC SECTION.
    CLASS-METHODS: get_by_type
      IMPORTING
                iv_data               TYPE any
      RETURNING VALUE(rt_ddfixvalues) TYPE ddfixvalues.
    CLASS-METHODS: get_by_name
      IMPORTING
                iv_name               TYPE domname
      RETURNING VALUE(rt_ddfixvalues) TYPE ddfixvalues.
ENDCLASS.

CLASS lcl_domvalues IMPLEMENTATION.

  METHOD get_by_type.
    TRY.
* liefert Typebeschreibung für DDIC-Typ
        rt_ddfixvalues = CAST cl_abap_elemdescr( cl_abap_typedescr=>describe_by_data( iv_data ) )->get_ddic_fixed_values( ).
      CATCH cx_root.
    ENDTRY.
  ENDMETHOD.

  METHOD get_by_name.
    TRY.
* liefert Typebeschreibung für DDIC-Typ
        rt_ddfixvalues = CAST cl_abap_elemdescr( cl_abap_typedescr=>describe_by_name( iv_name ) )->get_ddic_fixed_values( ).
      CATCH cx_root.
    ENDTRY.
  ENDMETHOD.

ENDCLASS.

START-OF-SELECTION.

* Domäne über Variablen-Typ
  DATA(lv_cat) = VALUE cccategory( ).
  DATA(it_by_type) = lcl_domvalues=>get_by_type( lv_cat ).

* Domäne über Name
  DATA(it_by_name) = lcl_domvalues=>get_by_name( 'CCCATEGORY' ).

  cl_demo_output=>write_data( it_by_type ).
  cl_demo_output=>write_data( it_by_name ).

  cl_demo_output=>display( ).

Variante 2 (DD_DOMVALUES_GET)

DATA(it_dd07v_tab) = VALUE dd07v_tab( ).
DATA(lv_rc) = VALUE sy-subrc( ).

CALL FUNCTION 'DD_DOMVALUES_GET'
  EXPORTING
    domname        = 'CCCATEGORY'
    text           = abap_true
*   LANGU          = ' '
*   BYPASS_BUFFER  = ' '
  IMPORTING
    rc             = lv_rc
  TABLES
    dd07v_tab      = it_dd07v_tab
  EXCEPTIONS
    wrong_textflag = 1
    OTHERS         = 2.

IF sy-subrc = 0.
  IF lv_rc = 0.
    cl_demo_output=>display( it_dd07v_tab ).
  ENDIF.
ENDIF.

Variante 3 (SQL)

* Name der Domäne
DATA(lv_domain) = 'CCCATEGORY'.
* Anmeldesprache
DATA(lv_lang) = cl_abap_syst=>get_logon_language( ).

SELECT l~domvalue_l, t~ddtext
  INTO TABLE @DATA(it_dom)
  FROM dd07l AS l
  INNER JOIN dd07t AS t ON l~domname = t~domname AND l~valpos = t~valpos AND l~domvalue_l = t~domvalue_l
  WHERE l~domname    = @lv_domain
    AND t~ddlanguage = @lv_lang.

cl_demo_output=>display( it_dom ).

Variante 4 (cl_reca_ddic_doma)

DATA(it_rsdomaval) = VALUE re_t_rsdomaval( ).

* DDIC-Objekt: Domäne
cl_reca_ddic_doma=>get_values( EXPORTING id_name   = 'CCCATEGORY'
                               IMPORTING et_values = it_rsdomaval ).

cl_demo_output=>display( it_rsdomaval ).

Variante 5 (cl_reca_ddic_doma)

DATA(lv_dd01v) = VALUE dd01v( ).
DATA(it_rsdomaval) = VALUE re_t_rsdomaval( ).

* DDIC-Objekt: Domäne
cl_reca_ddic_doma=>get_complete( EXPORTING id_name      = 'CCCATEGORY'
                                 IMPORTING es_header    = lv_dd01v
                                           et_rsdomaval = it_rsdomaval ).

cl_demo_output=>write_data( lv_dd01v ).
cl_demo_output=>write_data( it_rsdomaval ).
cl_demo_output=>display( ).

Links

[ABAP] Objekt-Referenzen in interner Tabelle (Liste) speichern

TYPES: BEGIN OF ty_user,
         bname      TYPE usr21-bname,
         persnumber TYPE adr6-persnumber,
         addrnumber TYPE adr6-addrnumber,
         smtp_addr  TYPE adr6-smtp_addr,
       END OF ty_user.

CLASS cl_person DEFINITION.
  PUBLIC SECTION.
    METHODS: constructor
      IMPORTING
        i_userdata TYPE ty_user.
    METHODS: print_mail.
  private SECTION.
    DATA: userdata TYPE ty_user.
ENDCLASS.

CLASS cl_person IMPLEMENTATION.
  METHOD constructor.
    userdata = i_userdata.
  ENDMETHOD.

  METHOD print_mail.
    WRITE: / userdata-bname, userdata-smtp_addr.
  ENDMETHOD.
ENDCLASS.

DATA: it_userdata TYPE TABLE OF ty_user.

* interne Tabelle zur Speicherung der Objektreferenzen
DATA: it_persons TYPE TABLE OF REF TO cl_person.
* Objektreferenz
DATA: o_person TYPE REF TO cl_person.

START-OF-SELECTION.
* Daten holen
  SELECT u~bname, u~persnumber, u~addrnumber, a~smtp_addr
    INTO CORRESPONDING FIELDS OF TABLE @it_userdata
    FROM usr21 AS u
    INNER JOIN adr6 AS a ON a~persnumber = u~persnumber AND a~addrnumber = u~addrnumber
    UP TO 10 ROWS.

* Objekte erzeugen und an Referenztabelle anhängen
  LOOP AT it_userdata INTO DATA(wa_user).
    o_person = new cl_person( wa_user ).
    APPEND o_person TO it_persons.
  ENDLOOP.

* Referenztabelle durchloopen und Objekte aufrufen
  LOOP AT it_persons INTO o_person.
    o_person->print_mail( ).
  ENDLOOP.

[ABAP] Generische Verarbeitung von internen Tabellen / Verwendung von Referenzen

* irgendeine interne Tablelle anlegen
DATA: it_tab TYPE STANDARD TABLE OF ...
* generische Tabellenreferenz anlegen
DATA: o_ref_table TYPE REF TO data.
 
...
 
* Tabellenreferenz übergeben
o_ref_table = REF #( it_tab ).
 
* Referenz auf generisches Feldsymbol mappen
FIELD-SYMBOLS: <tab> TYPE ANY TABLE.
ASSIGN o_ref_table->* TO <tab>.
 
* Tabellen-Zeile erzeugen
* muss hier erfolgen, damit man ein "greifbares" Tabellen-Zeilen-Objekt
* für die Strukturermittlung (describe_by_data) hat
DATA: o_row TYPE REF TO data.
CREATE DATA o_row LIKE LINE OF <tab>.
FIELD-SYMBOLS: <row> TYPE any.
ASSIGN o_row->* TO <row>.
 
* Komponenten (Spalten) einer Tabellenzeile ermitteln
DATA(o_struct) = CAST cl_abap_structdescr( cl_abap_typedescr=>describe_by_data( <row> ) ).
DATA(it_comp_tab) = o_struct->get_components( ).
 
* Anzahl Spalten der Tabellen-Zeile holen
DATA(lv_colcnt) = lines( it_comp_tab ).
 
* Tabelle durchloopen
LOOP AT <tab> ASSIGNING <row>.

* Spalten der akt. Zeile durchgehen
  DO lv_colcnt TIMES.
* Zelle: n-tes Element der akt. Zeile holen
    ASSIGN COMPONENT sy-index OF STRUCTURE <row> TO FIELD-SYMBOL(<cell>).
    
* Trennzeichen vor die Spalte einfügen, wenn nicht 1. Spalte
    IF sy-index > 1.
      WRITE: '|'.
    ENDIF.

* Achtung: Zell-Typ beachten! Es können hier nur flache Typen (Keine Strukturen, Tabellen) ausgegeben werden, der Rest muss gesondert behandelt werden
    IF CAST cl_abap_elemdescr( it_comp_tab[ sy-index ]-type )->kind = cl_abap_elemdescr=>kind_elem.
* Ausgabe Zellinhalt mit vordefinierter Spaltenbreite
      WRITE: |{ <cell> WIDTH = 20 |.
    ENDIF.
  ENDDO.

  NEW-LINE.
ENDLOOP.

[ABAP] Interne Tabelle als Datei (CSV) auf den lokalen Rechner speichern

DATA: itab TYPE STANDARD TABLE OF string.
DATA: lv_file TYPE string VALUE 'c:\temp\test.txt'.

...
 
TRY.
  cl_gui_frontend_services=>gui_download(
    EXPORTING
      filename = lv_file
      filetype = 'DAT'  " mögliche Filetypen: BIN, ASC, DAT, DBF, WK1, VSS, IBM
      codepage = '4110' " UTF-8 Encoding: 4110, UTF-16 Big Endian : 4102, UTF-16 Little Endian : 4103.    
    CHANGING
      data_tab = itab ).
  CATCH cx_root INTO DATA(e_text).
    MESSAGE e_text->get_text( ) TYPE 'I'.
ENDTRY.

Weiterführende Infos: Link

[ABAP] Beispiel für Implementation einer lokalen Klasse

CLASS cl_one DEFINITION.
* Public-Deklarationen, global inner- und außerhalb des Objektes sichtbar
  PUBLIC SECTION.
    DATA: pu_val3 TYPE i.        " dyn. Variable, nur zur Obj-Laufzeit verfügbar

    CLASS-DATA: txt TYPE string. " statische Public-Variable
    CLASS-DATA: int TYPE i.      " statische Public-Variable

* statische Methode, hat keinen Zugriff auf pu_val3
    CLASS-METHODS: function_one
      IMPORTING
                i_txt          TYPE string
      RETURNING VALUE(ret_val) TYPE string. " wenn RETURNING VALUE, dann kein EXPORTING oder CHANGING möglich

* statische Methode, hat keinen Zugriff auf pu_val3
    CLASS-METHODS: function_two
      IMPORTING
                i_txt          TYPE string
                i_val          TYPE i
      RETURNING VALUE(ret_val) TYPE string. " wenn RETURNING VALUE, dann kein EXPORTING oder CHANGING möglich

* dynamische Methode, hat Zugriff auf pu_val3
    METHODS: function_three
      IMPORTING
                i_val1         TYPE i DEFAULT 10 " Default-Wert, falls Parameter nicht gesetzt
                i_val2         TYPE i DEFAULT 20 " Default-Wert, falls Parameter nicht gesetzt
      RETURNING VALUE(ret_val) TYPE i.           " wenn RETURNING VALUE, dann kein EXPORTING oder CHANGING möglich

* dynamische Methode, einfaches Exceptionhandling
    METHODS: function_four
      IMPORTING
                i_val1         TYPE i
      RETURNING VALUE(ret_val) TYPE i
      RAISING   cx_sy_arithmetic_error.

    METHODS: constructor.
* Private-Deklarationen, nur innerhalb der Klasse sichtbar
  PRIVATE SECTION.
    DATA: pr_val3 TYPE i.
ENDCLASS.

CLASS cl_one IMPLEMENTATION.
* Constructor der Klasse
  METHOD constructor.
    me->pr_val3 = 100.
  ENDMETHOD.
* Funktion mit einem Übergabeparameter
  method function_one.
    DATA: s TYPE string VALUE 'Return: '.
    ret_val = |{ s } { i_txt }|.
  ENDMETHOD.

* Funktion mit zwei Übergabeparametern
  METHOD function_two.
    ret_val = |{ i_txt } { i_val }|.
  ENDMETHOD.

* Funktion mit zwei Übergabeparametern und DEFAULT-Werten
* Verwendung des me-> Operators für den Zugriff auf Attribute der Klasse
  METHOD function_three.
    ret_val = ( me->pu_val3 + me->pr_val3 ) * ( i_val1 + i_val2 ).
  ENDMETHOD.

* Funktion mit einem Übergabeparameter
* löst bei DIV0 -> cx_sy_arithmetic_error aus
  METHOD function_four.
    ret_val = 100 / i_val1.
  ENDMETHOD.
ENDCLASS.

INITIALIZATION.
  cl_one=>int = 1.
  cl_one=>txt = |Test.|.

START-OF-SELECTION.
* statische Objektaufrufe
  WRITE: / cl_one=>int.
  WRITE: / cl_one=>txt.

  WRITE: / cl_one=>function_one( |Input.| ).

  WRITE: / cl_one=>function_two( i_txt = |Input2:|
                                 i_val = 1 ).

* dynamische Objektaufrufe
  DATA(o_cl_one) = NEW cl_one( ).
  o_cl_one->pu_val3 = 10.
  WRITE: / o_cl_one->function_three( ).
  WRITE: / o_cl_one->function_three( i_val1 = 1
                                     i_val2 = 2 ).

* Exception abfangen
  TRY.
      WRITE: / o_cl_one->function_four( 0 ). " Division durch 0 auslösen
    CATCH cx_root INTO DATA(e_text).
      WRITE: / e_text->get_text( ).
  ENDTRY.

[ABAP] SALV-Table als F4-Suchhilfe-PopUp verwenden

CLASS lcl_salv_f4 DEFINITION.
  PUBLIC SECTION.
    CLASS-METHODS: get_selected_value
      IMPORTING
                i_table_name      TYPE string
                i_display_columns TYPE string DEFAULT '*'
                i_sel_column      TYPE string
                i_max_datacnt     TYPE i OPTIONAL
                i_top             TYPE i DEFAULT 3
                i_bottom          TYPE i DEFAULT 25
                i_left            TYPE i DEFAULT 25
                i_right           TYPE i DEFAULT 160
      RETURNING VALUE(ret_val)    TYPE string.
ENDCLASS.

CLASS lcl_salv_f4 IMPLEMENTATION.
  METHOD get_selected_value.

    ret_val = ''.

    TRY.
        IF i_display_columns NE ''.
* Datenreferenzen auf Table und Row
          DATA: o_table TYPE REF TO data.
          DATA: o_row TYPE REF TO data.

          FIELD-SYMBOLS: <table> TYPE STANDARD TABLE.
          FIELD-SYMBOLS: <row> TYPE any.

          CREATE DATA o_table TYPE STANDARD TABLE OF (i_table_name).
          ASSIGN o_table->* TO <table>.

          CREATE DATA o_row LIKE LINE OF <table>.
          ASSIGN o_row->* TO <row>.

* SELECT-Statement anpassen
          IF i_max_datacnt IS NOT INITIAL.
            SELECT (i_display_columns) FROM (i_table_name) INTO CORRESPONDING FIELDS OF TABLE @<table> UP TO @i_max_datacnt ROWS.
          ELSE.
            SELECT (i_display_columns) FROM (i_table_name) INTO CORRESPONDING FIELDS OF TABLE @<table>.
          ENDIF.

* SALV-Grid erzeugen
          DATA: o_salv TYPE REF TO cl_salv_table.

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

          o_salv->get_functions( )->set_default( abap_true ).
          o_salv->get_columns( )->set_optimize( abap_true ).
          o_salv->get_display_settings( )->set_striped_pattern( abap_true ).
          o_salv->get_selections( )->set_selection_mode( if_salv_c_selection_mode=>single ).
          o_salv->get_display_settings( )->set_list_header( 'Auswahl' ).

* Strukturbeschreibung einer Tabellenzeile
          DATA: o_struct TYPE REF TO cl_abap_structdescr.
          o_struct ?= cl_abap_typedescr=>describe_by_data( <row> ).

* Komponenten der Struktur
*          DATA: it_comp_tab TYPE abap_component_tab.
          DATA(it_comp_tab) = o_struct->get_components( ).

          DATA(it_columns) = o_salv->get_columns( ).
          DATA: lv_col TYPE REF TO cl_salv_column.

          LOOP AT it_comp_tab INTO DATA(lv_comp).
* Spalte anhand des Komponentennamens holen
            lv_col ?= it_columns->get_column( |{ lv_comp-name }| ).

* wenn Anzeigespalte als Komponente der Struktur verfügbar, dann Spalte anzeigen
            IF ( i_display_columns CS lv_comp-name ) OR ( i_display_columns = '*' ).
              lv_col->set_visible( abap_true ).
            ELSE.
              lv_col->set_visible( abap_false ).
            ENDIF.
          ENDLOOP.

* Popup-SALV-Grid anzeigen
          o_salv->set_screen_popup( start_column = i_left
                                    end_column   = i_right
                                    start_line   = i_top
                                    end_line     = i_bottom ).

* Popup anzeigen und auf Klick warten
          o_salv->display( ).

* Auswahl auswerten
          DATA(it_sel_rows) = o_salv->get_selections( )->get_selected_rows( ).

* Nummer der ersten gewählten Tabellenzeile holen -> it_sel_rows[ 1 ]
* Tabellenzeile ermitteln -> <table>[ ... ]
* und Feldwert anhand der Spaltennummer auslesen -> COMPONENT i_sel_column
          ASSIGN COMPONENT i_sel_column OF STRUCTURE <table>[ it_sel_rows[ 1 ] ] TO FIELD-SYMBOL(<cell>).

* Rückgabewert
          ret_val = <cell>.

        ENDIF.

      CATCH cx_root.

    ENDTRY.

  ENDMETHOD.
ENDCLASS.

PARAMETERS: p_par TYPE string OBLIGATORY.

AT SELECTION-SCREEN ON VALUE-REQUEST FOR p_par.
  p_par = lcl_salv_f4=>get_selected_value( i_table_name = 'spfli'
                                           i_display_columns = 'mandt, carrid, connid, cityto, airpfrom'
                                           i_sel_column = 'cityto' ).

[ABAP] Dynamische Tabelle anhand eines Tabellennamens erstellen, Daten ausgeben

DATA: table_name TYPE string VALUE 'spfli'. " Tabellenname
DATA: o_it TYPE REF TO data.                " Referenz auf Tabelle
DATA: o_row TYPE REF TO data.               " Referenz auf Tabellenzeile

FIELD-SYMBOLS: <fs_table> TYPE ANY TABLE.   " Feldsymbol für Arbeit mit Tabelle
FIELD-SYMBOLS: <fs_row> TYPE any.           " Feldsymbol für Arbeit mit Zeile

* dynamische Tabelle vom Typ table_name erzeugen
CREATE DATA o_it TYPE TABLE OF (table_name).
* Feldsymbol auf die dynamische Tabelle anlegen
ASSIGN o_it->* TO <fs_table>.

IF <fs_table> IS ASSIGNED.
* dynamische Workarea vom Typ der Tabellenzeile erzeugen
  CREATE DATA o_row LIKE LINE OF <fs_table>.
* Feldsymbol auf die Workarea anlegen
  ASSIGN o_row->* TO <fs_row>.

  IF <fs_row> IS ASSIGNED.
* Daten holen
    SELECT * FROM (table_name) INTO TABLE <fs_table>.

* Daten ausgeben
    DATA: go_struct TYPE REF TO cl_abap_structdescr.

* herausfinden, wieviele Spalten die Tabelle hat
    go_struct ?= cl_abap_typedescr=>describe_by_data( <fs_row> ).
    DATA(gt_comp) = go_struct->get_components( ).

* alle Datensätze der Tabelle durchgehen
    LOOP AT <fs_table> INTO <fs_row>.

* spaltenweise jeden Datensatz durchgehen
      LOOP AT gt_comp ASSIGNING FIELD-SYMBOL(<fs_col>).
* den Inhalt der Strukturkomponente (Zeile) ausgeben
        ASSIGN COMPONENT <fs_col>-name OF STRUCTURE <fs_row> TO FIELD-SYMBOL(<fs_cell>).

        IF <fs_cell> IS ASSIGNED.
          WRITE: <fs_cell>.
        ENDIF.
      ENDLOOP.

      NEW-LINE.

    ENDLOOP.
  ENDIF.
ENDIF.