[ABAP] XLSX-Datei mit Klasse cl_ehfnd_xlsx einlesen und in SALV-Grid anzeigen

TRY.
    DATA: lv_rc TYPE i.
    DATA: it_files TYPE filetable.
    DATA: lv_action TYPE i.

* FileOpen-Dialog aufrufen
    cl_gui_frontend_services=>file_open_dialog( EXPORTING file_filter = |xlsx (*.xlsx)\|*.xlsx\|{ cl_gui_frontend_services=>filetype_all }|
                                                CHANGING  file_table  = it_files
                                                          rc          = lv_rc
                                                          user_action = lv_action ).

    IF lv_action = cl_gui_frontend_services=>action_ok.
* wenn Datei ausgewählt wurde
      IF lines( it_files ) > 0.
* ersten Tabelleneintrag lesen
        DATA: lv_filesize TYPE w3param-cont_len.
        DATA: lv_filetype TYPE w3param-cont_type.
        DATA: it_bin_data TYPE w3mimetabtype.

* Excel-Datei auf Appl. Server hochladen (binary)
        cl_gui_frontend_services=>gui_upload( EXPORTING filename   = |{ it_files[ 1 ]-filename }|
                                                        filetype   = 'BIN'
                                              IMPORTING filelength = lv_filesize
                                              CHANGING  data_tab   = it_bin_data ).

* solix -> xstring
        DATA(lv_bin_data) = cl_bcs_convert=>solix_to_xstring( it_solix = it_bin_data ).

**********************************************************************
* XLSX Handling: Kapselt cl_xlsx_document
**********************************************************************
        DATA(o_excel) = cl_ehfnd_xlsx=>get_instance( ).

* XLSX Workbook (XString --> XML)
        DATA(o_doc) = o_excel->load_doc( iv_file_data = lv_bin_data ).

* XLSX Sheets des Workbooks holen
        DATA(it_sheets) = o_doc->get_sheets( ).

        IF lines( it_sheets ) > 0.
* XLSX Sheet: erste Sheet holen
          DATA(o_sheet) = o_doc->get_sheet_by_id( iv_sheet_id = 1 ).
          DATA(lv_sheet_name) = it_sheets[ 1 ]-name.

* max. Zeilenzahl der Sheet
          DATA(lv_max_rows) = o_sheet->get_last_row_number( ).
          DATA(lv_max_cols) = o_sheet->get_last_column_number_in_row( 1 ).

          IF lv_max_rows > 0 AND lv_max_cols > 0.
* Komponenten (Spalten) der Tabelle --> generische Stringtable bauen
            DATA(it_components) = VALUE cl_abap_structdescr=>component_table( ).

* Überschriften (Header) für ALV-Grid
            DATA(it_colnames) = VALUE stringtab( ).

            DO lv_max_cols TIMES.
* Spaltenbezeichner aus 1. Zeile (Header) der Excel-Tabelle holen
              DATA(lv_col_header) = o_sheet->get_cell_content( iv_row    = 1
                                                               iv_column = sy-index ).

* alle Vorkommen, die nicht [a-zA-Z0-9_] entsprechen, durch '_' ersetzen
              REPLACE ALL OCCURRENCES OF REGEX '([^\w]|[äöüÄÖÜß])+' IN lv_col_header WITH '_'.

* Tabelle mit Überschriften für ALV-Grid füllen
              APPEND lv_col_header TO it_colnames.

* Spalte vom Typ String mit generischem Namen zur Komponententabelle hinzufügen
              APPEND VALUE #( name   = |COL{ sy-index }|
                              type   = cl_abap_elemdescr=>get_string( )
                            ) TO it_components.
            ENDDO.

**********************************************************************
* generische interne Tabelle mit hilfe dynamischer Objekte erzeugen
**********************************************************************
* Strukturdeskriptor für Komponententabelle erzeugen
            DATA(o_struct_desc) = cl_abap_structdescr=>create( it_components ).

* Tabellendeskriptor erzeugen
            DATA(o_table_desc) = cl_abap_tabledescr=>create( p_line_type = o_struct_desc ).

* dynamisches Tabellenobjekt anhand des Tabellendeskriptors erstellen
            DATA: o_table TYPE REF TO data.
            CREATE DATA o_table TYPE HANDLE o_table_desc.

* Feldsymbol auf das Tabellenobjekt vom Typ STANDARD TABLE anlegen
            FIELD-SYMBOLS <table> TYPE STANDARD TABLE.
            ASSIGN o_table->* TO <table>.

* Inhalt (ohne Header) aus XLSX in interne Tabelle schreiben
            DATA(lv_row) = 2.

            DO lv_max_rows - 1 TIMES.
              DATA(lv_col) = 1.

* neue Ausgabezeile anfügen
              APPEND INITIAL LINE TO <table>.

* neue Ausgabezeile holen und Feldsymbol zuweisen
              DATA(lv_lc) = lines( <table> ).
              ASSIGN <table>[ lv_lc ] TO FIELD-SYMBOL(<row>).

              IF <row> IS ASSIGNED.
* für alle Spalten der Tabelle
                DO lv_max_cols TIMES.
* n-te Spalte <col> der akt. Tabellenzeile <row> ermitteln
                  ASSIGN COMPONENT lv_col OF STRUCTURE <row> TO FIELD-SYMBOL(<cell>).
                  IF <cell> IS ASSIGNED.
* Inhalt der akt. Zelle in die Zelle der internen Tabelle schreiben
                    <cell> = o_sheet->get_cell_content( iv_row    = lv_row
                                                        iv_column = lv_col ).


                  ENDIF.

                  lv_col = lv_col + 1.
                ENDDO.
              ENDIF.

              lv_row = lv_row + 1.
            ENDDO.

**********************************************************************
* Anzeige der gefüllten generischen Tabelle in einem SALV-Grid
**********************************************************************
            TRY.
*             SALV-Table
                DATA: o_salv TYPE REF TO cl_salv_table.

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

*             Grundeinstellungen
                o_salv->get_functions( )->set_all( abap_true ).
                o_salv->get_columns( )->set_optimize( abap_true ).
                o_salv->get_display_settings( )->set_list_header( CONV #( lv_sheet_name ) ).
                o_salv->get_display_settings( )->set_striped_pattern( abap_true ).
                o_salv->get_selections( )->set_selection_mode( if_salv_c_selection_mode=>row_column ).

*             Spaltenüberschriften: technischer Name und Beschreibungstexte, Short Text und Medium Text leer lassen für Autosize
                LOOP AT o_salv->get_columns( )->get( ) ASSIGNING FIELD-SYMBOL(<c>).
                  DATA(lv_idx) = sy-tabix.

                  DATA(o_col) = <c>-r_column.
                  o_col->set_short_text( || ).
                  o_col->set_medium_text( || ).
                  o_col->set_long_text( CONV #( it_colnames[ lv_idx ] ) ).
                ENDLOOP.

                o_salv->display( ).
              CATCH cx_root INTO DATA(e_txt).
                WRITE: / e_txt->get_text( ).
            ENDTRY.
          ENDIF.

        ENDIF.

      ENDIF.

    ENDIF.

  CATCH cx_root INTO DATA(e_text).
    MESSAGE e_text->get_text( ) TYPE 'S' DISPLAY LIKE 'E'.
ENDTRY.

[ABAP] MS-Excel-Datei mit Hilfe der Klasse cl_ehfnd_xlsx lesen

TRY.
    DATA: lv_rc TYPE i.
    DATA: it_files TYPE filetable.
    DATA: lv_action TYPE i.

* FileOpen-Dialog aufrufen
    cl_gui_frontend_services=>file_open_dialog( EXPORTING file_filter = |xlsx (*.xlsx)\|*.xlsx\|{ cl_gui_frontend_services=>filetype_all }|
                                                CHANGING  file_table  = it_files
                                                          rc          = lv_rc
                                                          user_action = lv_action ).

    IF lv_action = cl_gui_frontend_services=>action_ok.
* wenn Datei ausgewählt wurde
      IF lines( it_files ) > 0.
* ersten Tabelleneintrag lesen
        DATA: lv_filesize TYPE w3param-cont_len.
        DATA: lv_filetype TYPE w3param-cont_type.
        DATA: it_bin_data TYPE w3mimetabtype.

* Excel-Datei auf Appl. Server hochladen (binary)
        cl_gui_frontend_services=>gui_upload( EXPORTING filename   = |{ it_files[ 1 ]-filename }|
                                                        filetype   = 'BIN'
                                              IMPORTING filelength = lv_filesize
                                              CHANGING  data_tab   = it_bin_data ).

* solix -> xstring
        DATA(lv_bin_data) = cl_bcs_convert=>solix_to_xstring( it_solix = it_bin_data ).

* XLSX Handling: Kapselt cl_xlsx_document
        DATA(o_excel) = cl_ehfnd_xlsx=>get_instance( ).

* XLSX Workbook (XString --> XML)
        DATA(o_doc) = o_excel->load_doc( iv_file_data = lv_bin_data ).

* XLSX Sheets des Workbooks holen
        DATA(it_sheets) = o_doc->get_sheets( ).

        LOOP AT it_sheets ASSIGNING FIELD-SYMBOL(<sheet>).
          WRITE: / <sheet>-name, <sheet>-sheet_id, <sheet>-rid.
        ENDLOOP.

        ULINE.

* XLSX Sheet: erste Sheet holen
        DATA(o_sheet) = o_doc->get_sheet_by_id( iv_sheet_id = 1 ).
* max. Zeilenzahl der Sheet
        DATA(lv_maxrow) = o_sheet->get_last_row_number( ).

        DATA(lv_row) = 1.

        DO lv_maxrow TIMES.
* max. Spaltenzahl der akt. Zeile
          DATA(lv_cols_in_row) = o_sheet->get_last_column_number_in_row( lv_row ).
          DATA(lv_col) = 1.

          DO lv_cols_in_row TIMES.
* Inhalt der akt. Zelle
            DATA(lv_value) = o_sheet->get_cell_content( EXPORTING iv_row    = lv_row
                                                                  iv_column = lv_col ).

            WRITE: lv_value.

            lv_col = lv_col + 1.
          ENDDO.

          lv_row = lv_row + 1.

          WRITE: /.
        ENDDO.

      ENDIF.
    ENDIF.

  CATCH cx_root INTO DATA(e_text).
    MESSAGE e_text->get_text( ) TYPE 'S' DISPLAY LIKE 'E'.
ENDTRY.

[ABAP] Beispiel für Verwendung der Klasse cl_xlsx_document

* Workbook
PARAMETERS: p_wb RADIOBUTTON GROUP grp DEFAULT 'X'.
* Sharedstrings
PARAMETERS: p_str RADIOBUTTON GROUP grp.
* Sheetpart
PARAMETERS: p_sh RADIOBUTTON GROUP grp.
* Tablepart
PARAMETERS: p_tab RADIOBUTTON GROUP grp.

START-OF-SELECTION.

  TRY.
      DATA: lv_rc TYPE i.
      DATA: it_files TYPE filetable.
      DATA: lv_action TYPE i.

* FileOpen-Dialog aufrufen
      cl_gui_frontend_services=>file_open_dialog( EXPORTING file_filter = |xlsx (*.xlsx)\|*.xlsx\|{ cl_gui_frontend_services=>filetype_all }|
                                                  CHANGING  file_table  = it_files
                                                            rc          = lv_rc
                                                            user_action = lv_action ).

      IF lv_action = cl_gui_frontend_services=>action_ok.
* wenn Datei ausgewählt wurde
        IF lines( it_files ) > 0.
* ersten Tabelleneintrag lesen
          DATA: lv_filesize TYPE w3param-cont_len.
          DATA: lv_filetype TYPE w3param-cont_type.
          DATA: it_bin_data TYPE w3mimetabtype.

* Excel-Datei auf Appl. Server hochladen (binary)
          cl_gui_frontend_services=>gui_upload( EXPORTING filename   = |{ it_files[ 1 ]-filename }|
                                                          filetype   = 'BIN'
                                                IMPORTING filelength = lv_filesize
                                                CHANGING  data_tab   = it_bin_data ).

* solix -> xstring
          DATA(lv_bin_data) = cl_bcs_convert=>solix_to_xstring( it_solix = it_bin_data ).

**********************************************************************
* Excel-Objekt
**********************************************************************
          DATA(o_excel) = cl_xlsx_document=>load_document( lv_bin_data ).

          DATA(o_workbook) = o_excel->get_workbookpart( ).
          DATA(lv_workbook_xstr) = o_workbook->get_data( ).

          DATA(o_sharedstrings) = o_workbook->get_sharedstringspart( ).
          DATA(lv_sharedstrings_xstr) = o_sharedstrings->get_data( ).

          DATA(o_sheets) = o_workbook->get_worksheetparts( ).
          IF o_sheets->get_count( ) > 0.
            DATA(o_sheet) = CAST cl_xlsx_worksheetpart( o_sheets->get_part( 0 ) ).

            DATA(lv_sheet_xstr) = o_sheet->get_data( ).

            DATA(o_tables) = o_sheet->get_tableparts( ).
            IF o_tables->get_count( ) > 0.
              DATA(o_table) = CAST cl_xlsx_tablepart( o_tables->get_part( 0 ) ).
              DATA(lv_table_xstr) = o_table->get_data( ).
            ENDIF.
          ENDIF.

* XML Doc
          DATA(o_doc) = NEW cl_xml_document( ).

* xstring --> xml
          CASE abap_true.
            WHEN p_wb.
              o_doc->parse_xstring( lv_workbook_xstr ).
            WHEN p_str.
              o_doc->parse_xstring( lv_sharedstrings_xstr ).
            WHEN p_sh.
              o_doc->parse_xstring( lv_sheet_xstr ).
            WHEN p_tab.
              o_doc->parse_xstring( lv_table_xstr ).
          ENDCASE.

* Inhalt des XML-Documents in string wandeln
          o_doc->render_2_string( EXPORTING pretty_print = abap_true
                                  IMPORTING retcode      = DATA(lv_rc2)
                                            size         = DATA(lv_size2)
                                            stream       = DATA(lv_xml) ).

          IF lv_rc2 = 0.
* XML-String anzeigen
            cl_soap_xml_helper=>xml_show( sdoc  = lv_xml
                                          html  = abap_true
                                          title = 'XML Anzeige' ).
          ENDIF.

        ENDIF.
      ENDIF.

    CATCH cx_root INTO DATA(e_text).
      MESSAGE e_text->get_text( ) TYPE 'S' DISPLAY LIKE 'E'.
  ENDTRY.

[ABAP] Datenbanktabellen mittels SE16N editieren

* Tabellename
PARAMETERS: lv_tab TYPE se16n_tab DEFAULT 'T024'.
* max. Anzahl Datensätze für die Anzeige
PARAMETERS: lv_maxl TYPE sytabix DEFAULT 500.
* Edit-Parameter, diese entsprechen den Variablen GD-EDIT und GD-SAPEDIT in der SE16N
PARAMETERS: lv_edit TYPE abap_bool AS CHECKBOX DEFAULT abap_true.
PARAMETERS: lv_sedit TYPE abap_bool AS CHECKBOX DEFAULT abap_true.
* Mandantenspalte ausblenden
PARAMETERS: lv_clnt TYPE abap_bool AS CHECKBOX DEFAULT abap_false.
* technische Namen anzeigen
PARAMETERS: lv_tech TYPE abap_bool AS CHECKBOX DEFAULT abap_false.

INITIALIZATION.
  %_lv_tab_%_app_%-text = 'Tabelle:'.
  %_lv_edit_%_app_%-text = 'Edit Parameter 1 (GD-EDIT)'.
  %_lv_sedit_%_app_%-text = 'Edit Parameter 2 (GD-SAPEDIT)'.
  %_lv_maxl_%_app_%-text = 'Maximale Trefferzahl'.
  %_lv_clnt_%_app_%-text = 'Tabelle ist mandantenabhängig'.
  %_lv_tech_%_app_%-text = 'Technische Namen'.

START-OF-SELECTION.
* Anzeige einer Tabelle als Vollbild, analog SE16N
* Achtung: Tabelle lv_tab kann analog zum bekannten SE16N-Parameter &sap_edit vollumfänglich editiert werden,
*          dies kann bei Fehlbedienung zu Dateninkonsistenzen führen --> Funktion daher nicht im Produktivsystem verwenden!
  CALL FUNCTION 'SE16N_INTERFACE'
    EXPORTING
      i_tab        = lv_tab
      i_edit       = lv_edit
      i_sapedit    = lv_sedit
      i_max_lines  = lv_maxl
      i_clnt_dep   = lv_clnt
      i_tech_names = lv_tech
* CHANGING
*     IT_AND_SELFIELDS            =
    EXCEPTIONS
      no_values    = 1
      OTHERS       = 2.

  IF sy-subrc <> 0.
    WRITE: / 'Fehler:', sy-subrc.
  ENDIF.

Links

[ABAP] Testen, ob per RFC ein Funktionsbaustein im Zielsystem vorhanden ist

* https://www.berater-wiki.de/RFC-Funktionsbausteine
* https://download.consolut.com/direct/SAP_PrintDoku/de/BCFESDE2/BCFESDE2.PDF

* Funktionsbaustein-Name, verwendet Suchhilfe pb_func_key
PARAMETERS: p_func TYPE rs38l_fnam MATCHCODE OBJECT pb_func_key.
* RFC-Verbindung
PARAMETERS: p_rfc TYPE rfcdest.

START-OF-SELECTION.

* Nachschauen, ob RFC-Verbindung vorhanden
  SELECT SINGLE d~rfcdest, d~rfctype, d~rfcoptions, t~rfcdoc1, t~rfcdoc2, t~rfcdoc3
    INTO @DATA(lv_rfc)
    FROM rfcdes AS d
    INNER JOIN rfcdoc AS t ON ( d~rfcdest = t~rfcdest )
    WHERE d~rfcdest = @p_rfc
      AND t~rfclang = @sy-langu.

  IF sy-subrc = 0.
    DATA: lv_err_msg TYPE char255.
* wenn RFC-Verbindung vorhanden -> anpingen und Systemfehler (Dumps) abfangen
    CALL FUNCTION 'RFC_PING' DESTINATION p_rfc
      EXCEPTIONS
        system_failure        = 1 MESSAGE lv_err_msg
        communication_failure = 2 MESSAGE lv_err_msg
        OTHERS                = 3.

    IF sy-subrc = 0.
* RFC-Ping ok
      WRITE: / '[', p_rfc, '] RFC-Aufruf erfolgreich.'.

* Existenzprüfung und Funktionsgruppe zu Funktionsbaustein besorgen
      CALL FUNCTION 'FUNCTION_EXISTS' DESTINATION p_rfc
        EXPORTING
          funcname           = p_func
        EXCEPTIONS
          function_not_exist = 1
          OTHERS             = 2.

      IF sy-subrc = 0.
        WRITE: / 'Funktionsbaustein:', p_func, 'existiert im Zielsystem:', p_rfc.
      ELSE.
        WRITE: / 'Funktionsbaustein:', p_func, 'existiert nicht im Zielsystem:', p_rfc.
      ENDIF.
    ELSE.
* RFC-Ping fehlerhaft
      WRITE: / '[', p_rfc, '] RFC-Aufruf gescheitert:', lv_err_msg.
    ENDIF.
  ELSE.
* RFC-Verbindung nicht vorhanden
    WRITE: / '[', p_rfc, '] RFC-Verbindung nicht vorhanden.'.
  ENDIF.

[ABAP] Editierbares SALV-Grid (IF_SALV_GUI_OM_EXTEND_GRID_API, IF_SALV_GUI_OM_EDIT_RESTRICTED)

* Quelle: https://blogs.sap.com/2022/08/01/editable-cl_salv_table-after-release-756/
* ab SAP Release 756
* Achtung: das Ganze funktioniert nur für kleine Tabellen mit max. 5000 Zellen, siehe:
*
* Methode: CL_SALV_GUI_OM_ADAPTER_TABLE->CAN_RUN_RESTRICTED_EDIT_MODE( )
* Konstante: CV_MAX_CELLS_FOR_EDITABLE (Wert: 5000).

* Eventhandler
CLASS lcl_events DEFINITION.
  PUBLIC SECTION.
* Bezeichner der Buttons
    CONSTANTS: co_btn_edit TYPE string VALUE 'BTN_EDIT'.
    CONSTANTS: co_btn_save TYPE string VALUE 'BTN_SAVE'.

* Platzhalter für Referenz auf SALV-Grid
    CLASS-DATA: o_salv TYPE REF TO cl_salv_table.

* Eventhandler-Methode für Button-Klicks in der Toolbar des SALV-Grids
    CLASS-METHODS : on_toolbar_click FOR EVENT added_function OF cl_salv_events_table
      IMPORTING
        e_salv_function
        sender.
  PRIVATE SECTION.
* Edit-Status des SALV-Grids
    CLASS-DATA: gv_edit TYPE abap_bool VALUE abap_false.
ENDCLASS.

CLASS lcl_events IMPLEMENTATION.
  METHOD on_toolbar_click.
    IF o_salv IS BOUND.

      DATA(o_api) = o_salv->extended_grid_api( ).
      DATA(o_edit) = o_api->editable_restricted( ).

      CASE e_salv_function.

        WHEN co_btn_edit.
* Edit-Modus umschalten
          IF gv_edit = abap_false.
            gv_edit = abap_true.
          ELSE.
            gv_edit = abap_false.
          ENDIF.

          TRY.
* Spalte(n) (nicht) editierbar setzen
              o_edit->set_attributes_for_columnname( EXPORTING columnname              = 'EKGRP'
                                                               all_cells_input_enabled = gv_edit ).

              o_edit->set_attributes_for_columnname( EXPORTING columnname              = 'SMTP_ADDR'
                                                               all_cells_input_enabled = gv_edit ).
            CATCH cx_salv_not_found.
          ENDTRY.

          o_edit->validate_changed_data( ).
          o_salv->refresh( ).

        WHEN co_btn_save.
* Daten auf Validität prüfen
          DATA(lv_data_is_valid) = abap_false.

          TRY.
              o_edit->validate_changed_data( IMPORTING is_input_data_valid = lv_data_is_valid ).
              o_salv->refresh( ).
            CATCH cx_salv_not_found.
          ENDTRY.

          IF lv_data_is_valid = abap_true.
* Daten hier speichern / weiterverarbeiten
            MESSAGE co_btn_save TYPE 'I'.
          ENDIF.
      ENDCASE.
    ENDIF.
  ENDMETHOD.
ENDCLASS.

START-OF-SELECTION.

  TRY.
* Beispieldaten (Einkäufergruppen) holen
      SELECT FROM t024
        FIELDS *
        INTO TABLE @DATA(it_t024).

      IF sy-subrc = 0.
        cl_salv_table=>factory( EXPORTING r_container  = cl_gui_container=>default_screen
                                IMPORTING r_salv_table = lcl_events=>o_salv
                                CHANGING  t_table      = it_t024 ).

* Standardbuttons der SALV-Table ausblenden
        lcl_events=>o_salv->get_functions( )->set_all( abap_false ).

* Eigenen SALV-Button hinzufügen
* das Hinzufügen des Buttons funktioniert nur, wenn die SALV-Table innerhalb eines Containers (z.B. cl_gui_container=>default_screen) eingebettet ist
        lcl_events=>o_salv->get_functions( )->add_function( name = |{ lcl_events=>co_btn_edit }|
                                                            icon = |{ icon_edit_file }|
                                                            text = 'Edit'
                                                            tooltip = 'Daten editieren'
                                                            position = if_salv_c_function_position=>right_of_salv_functions ).

        lcl_events=>o_salv->get_functions( )->add_function( name = |{ lcl_events=>co_btn_save }|
                                                            icon = |{ icon_save_as_template }|
                                                            text = 'Save'
                                                            tooltip = 'Daten speichern'
                                                            position = if_salv_c_function_position=>right_of_salv_functions ).

* Eventhandler für Klicks in die Toolbar des SALV-Grids setzen
        SET HANDLER lcl_events=>on_toolbar_click FOR lcl_events=>o_salv->get_event( ).

* SALV anzeigen
        lcl_events=>o_salv->display( ).

* Toolbar der Listausgabe unterdrücken
        cl_abap_list_layout=>suppress_toolbar( ).

* Listausgabe erzwingen für Erzeugung von cl_gui_container=>default_screen
        WRITE: space.

      ENDIF.
    CATCH cx_root INTO DATA(e_txt).
      WRITE: / e_txt->get_text( ).
  ENDTRY.

[ABAP] Neues SAP-Fenster (Modus) öffnen und wieder schließen

* Bsp.: Transaktion SU3
PARAMETERS: p_tcode TYPE tcode DEFAULT 'SU3'.

START-OF-SELECTION.

  DATA: lv_mode TYPE sy-index.

* Eröffnen eines neuen externen Modus
  CALL FUNCTION 'TH_CREATE_MODE'
    EXPORTING
      transaktion    = p_tcode
    IMPORTING
      mode           = lv_mode
    EXCEPTIONS
      max_sessions   = 1
      internal_error = 2
      no_authority   = 3
      OTHERS         = 4.

  IF sy-subrc = 0.
    WRITE: / 'Transaktion:', p_tcode.
    WRITE: / 'Modus:', lv_mode.

    DATA: ret TYPE string.

    CALL FUNCTION 'POPUP_TO_CONFIRM'
      EXPORTING
        titlebar              = 'Modus'
        text_question         = 'Modus wieder schließen?'
        display_cancel_button = abap_false
      IMPORTING
        answer                = ret.

    CASE ret.
      WHEN '1'.
* Löschen eines externen Modus
        CALL FUNCTION 'TH_DELETE_MODE'
          EXPORTING
            mode = lv_mode.
      WHEN OTHERS.
    ENDCASE.
  ENDIF.

[ABAP] Infos zu Datenelementen und Domänen lesen

* Name Datenelement
PARAMETERS: p_dtype TYPE ddobjname DEFAULT 'CCCATEGORY'.

START-OF-SELECTION.

  DATA: lv_gotstate	TYPE ddgotstate.
  DATA: lv_dd04v_wa	TYPE dd04v.
  DATA: lv_tpara_wa	TYPE tpara.

* DD: Schnittstelle zum Lesen eines Datenelements aus dem ABAP/4 Dictionary
  CALL FUNCTION 'DDIF_DTEL_GET'
    EXPORTING
      name          = p_dtype
    IMPORTING
      gotstate      = lv_gotstate
      dd04v_wa      = lv_dd04v_wa
      tpara_wa      = lv_tpara_wa
    EXCEPTIONS
      illegal_input = 1
      OTHERS        = 2.

  IF sy-subrc = 0.
    DATA: lv_gotstate_d	TYPE ddgotstate.
    DATA: lv_dd01v_wa	TYPE dd01v.
    DATA: it_dd07v_tab TYPE STANDARD TABLE OF dd07v WITH DEFAULT KEY.

* DD: Schnittstelle zum Lesen einer Domäne aus dem ABAP/4 Dictionary
    CALL FUNCTION 'DDIF_DOMA_GET'
      EXPORTING
        name          = lv_dd04v_wa-domname
      IMPORTING
        gotstate      = lv_gotstate_d
        dd01v_wa      = lv_dd01v_wa
      TABLES
        dd07v_tab     = it_dd07v_tab
      EXCEPTIONS
        illegal_input = 1
        OTHERS        = 2.

    IF sy-subrc = 0.
      cl_demo_output=>next_section( |Datentyp { p_dtype }| ).
      cl_demo_output=>write_data( lv_gotstate ).
      cl_demo_output=>write_data( lv_dd04v_wa ).
      cl_demo_output=>write_data( lv_tpara_wa ).

      cl_demo_output=>next_section( |Domäne { lv_dd04v_wa-domname }| ).
      cl_demo_output=>write_data( lv_gotstate_d ).
      cl_demo_output=>write_data( lv_dd01v_wa ).
      cl_demo_output=>write_data( it_dd07v_tab ).

* HTML-Code vom Demo-Output holen
      DATA(lv_html) = cl_demo_output=>get( ).

* Daten im Inline-Browser im SAP-Fenster anzeigen
      cl_abap_browser=>show_html( EXPORTING
                                    title        = 'Infos'
                                    html_string  = lv_html
                                    container    = cl_gui_container=>default_screen ).

* cl_gui_container=>default_screen erzwingen
      WRITE: space.
    ENDIF.
  ENDIF.

[ABAP] Informationen zu einem Dynpro ermitteln

SELECTION-SCREEN BEGIN OF LINE.
  SELECTION-SCREEN COMMENT (9) lbl1 FOR FIELD p_matnr.
  PARAMETERS: p_matnr TYPE matnr.
SELECTION-SCREEN END OF LINE.

INITIALIZATION.
  lbl1 = 'Material:'.

START-OF-SELECTION.

  DATA: lv_header TYPE rpy_dyhead.
  DATA: it_containers TYPE dycatt_tab.
  DATA: it_fields_to_containers TYPE dyfatc_tab.
  DATA: it_flow_logic TYPE swydyflow.

* Lesen eines Dynpros
  CALL FUNCTION 'RPY_DYNPRO_READ'
    EXPORTING
      progname             = sy-cprog
      dynnr                = sy-dynnr
    IMPORTING
      header               = lv_header
    TABLES
      containers           = it_containers
      fields_to_containers = it_fields_to_containers
      flow_logic           = it_flow_logic
    EXCEPTIONS
      cancelled            = 1
      not_found            = 2
      permission_error     = 3
      OTHERS               = 4.

  IF sy-subrc = 0.
    cl_demo_output=>write_data( lv_header ).
    cl_demo_output=>write_data( it_containers ).
    cl_demo_output=>write_data( it_fields_to_containers ).
    cl_demo_output=>write_data( it_flow_logic ).

* HTML-Code vom Demo-Output holen
    DATA(lv_html) = cl_demo_output=>get( ).

* Daten im Inline-Browser im SAP-Fenster anzeigen
    cl_abap_browser=>show_html( EXPORTING
                                  title        = |Daten des Dynpros { sy-dynnr }|
                                  html_string  = lv_html
                                  container    = cl_gui_container=>default_screen ).

* cl_gui_container=>default_screen erzwingen
    WRITE: space.
  ENDIF.