[ABAP] QR-Codes als Bitmap erzeugen

* Docking-Container für Einbettung cl_gui_picture
DATA: o_dock TYPE REF TO cl_gui_docking_container.

* Text für QR-Code
PARAMETERS: p_text TYPE string DEFAULT 'https://google.de' LOWER CASE.

AT SELECTION-SCREEN OUTPUT.

  TRY.
      IF NOT o_dock IS BOUND.
* Dockingcontainer erzeugen
        o_dock = NEW #( repid = sy-repid
                        dynnr = sy-dynnr
                        side  = cl_gui_docking_container=>dock_at_right
                        ratio = 50 ).
      ENDIF.

      DATA: lv_xstr_bmp TYPE xstring.

* Siehe https://me.sap.com/notes/2790500
* Siehe https://me.sap.com/notes/2030263
* i_module_size      - Größe des Barcodes in 1-32000 Pixel, wobei 1 Pixel == ein 1/600 Zoll großer Punkt
* i_barcode_text     - Textinhalt
* i_mode             - A - AUTOMATIC
*                      N - NUMERIC
*                      L - ALPHANUMERIC
*                      B - BYTE_LATIN1
*                      K - KANJI
*                      U - BYTE_UTF8
*                      1 - FNC1_POS1 (FNC1 an erster Position)
*                      2 - FNC1_POS2 (FNC1 an zweiter Position)
* i_error_correction - Fehlerkorrekturwert (L - 7%, M - 15%, Q - 25%, H - 30%)
* i_rotation         - Barcode-Ausrichtung: 0 - NORMAL, 90 - ROTATED, 180 - INVERTED, 270 - BOTTOMUP
* Process QR Code barcode
      cl_rstx_barcode_renderer=>qr_code( EXPORTING i_module_size  = 50
                                                   i_barcode_text = p_text
*                                                 i_mode             = 'A'
*                                                 i_error_correction = 'H'
*                                                 i_rotation         = 0
                                         IMPORTING e_bitmap       = lv_xstr_bmp ).

      DATA(it_bin_bmp) = cl_bcs_convert=>xstring_to_solix( lv_xstr_bmp ).

      DATA: lv_url TYPE swk_url.

* temporäre URL auf das Bild erzeugen
      CALL FUNCTION 'DP_CREATE_URL'
        EXPORTING
          type                 = 'image/bmp' " https://wiki.selfhtml.org/wiki/MIME-Type/%C3%9Cbersicht
          subtype              = 'bmp'
        TABLES
          data                 = it_bin_bmp
        CHANGING
          url                  = lv_url
        EXCEPTIONS
          dp_invalid_parameter = 1
          dp_error_put_table   = 2
          dp_error_general     = 3
          OTHERS               = 4.

* Bild über die URL laden und anzeigen
      DATA(o_pic) = NEW cl_gui_picture( parent = o_dock ).
      o_pic->set_display_mode( display_mode = cl_gui_picture=>display_mode_fit_center ).
      o_pic->load_picture_from_url_async( lv_url ).

* Flush ist wichtig für die Abarbeitung des GUI-Queues, sonst gibt es einen Core-Dump -> "SYSTEM_POINTER_PENDING"
      cl_gui_cfw=>flush( ).

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

[ABAP] Code128-Barcode als Bitmap erzeugen

* Docking-Container für Einbettung cl_gui_picture
DATA: o_dock TYPE REF TO cl_gui_docking_container.

* Text für Barcode
PARAMETERS: p_text TYPE string DEFAULT '1234567890' LOWER CASE.

AT SELECTION-SCREEN OUTPUT.

  TRY.
      IF NOT o_dock IS BOUND.
* Dockingcontainer erzeugen
        o_dock = NEW #( repid = sy-repid
                        dynnr = sy-dynnr
                        side  = cl_gui_docking_container=>dock_at_right
                        ratio = 50 ).
      ENDIF.

      DATA: lv_xstr_bmp TYPE xstring.

* Siehe: https://me.sap.com/notes/2790500
* Siehe: https://me.sap.com/notes/645158
* i_narrow_module_width - 1 ... 10, Breite für das schmalste Modul eines Barcodes in Pixeln
* i_height              - 1 ... 9999, Höhe der Balken des Barcodes in Pixeln (600 px == 1 Zoll)
* i_mode                - N (None), A (Automatic), U (UCC case mode)
* i_rotation            - 0 - Normal, 90 -  Rotated, 180 - Inverted, 270 - Bottomup
* Process Code 128 barcode
      cl_rstx_barcode_renderer=>code_128( EXPORTING i_narrow_module_width = 1
                                                    i_height              = 50
*                                                    i_mode                = 'A'
*                                                    i_rotation            = 0
                                                    i_barcode_text        = p_text
                                          IMPORTING e_bitmap              = lv_xstr_bmp ).

      DATA(it_bin_bmp) = cl_bcs_convert=>xstring_to_solix( lv_xstr_bmp ).

      DATA: lv_url TYPE swk_url.

* temporäre URL auf das Bild erzeugen
      CALL FUNCTION 'DP_CREATE_URL'
        EXPORTING
          type                 = 'image/bmp' " https://wiki.selfhtml.org/wiki/MIME-Type/%C3%9Cbersicht
          subtype              = 'bmp'
        TABLES
          data                 = it_bin_bmp
        CHANGING
          url                  = lv_url
        EXCEPTIONS
          dp_invalid_parameter = 1
          dp_error_put_table   = 2
          dp_error_general     = 3
          OTHERS               = 4.

* Bild über die URL laden und anzeigen
      DATA(o_pic) = NEW cl_gui_picture( parent = o_dock ).
      o_pic->set_display_mode( display_mode = cl_gui_picture=>display_mode_fit_center ).
      o_pic->load_picture_from_url_async( lv_url ).

* Flush ist wichtig für die Abarbeitung des GUI-Queues, sonst gibt es einen Core-Dump -> "SYSTEM_POINTER_PENDING"
      cl_gui_cfw=>flush( ).

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

[ABAP] Eventhandling für die Klasse cl_gui_picture

* Demoprogramm: SAP_PICTURE_DEMO

* Eventhandlerklasse
CLASS lcl_events DEFINITION.
  PUBLIC SECTION.
    CLASS-METHODS: on_picture_dblclick FOR EVENT picture_dblclick OF cl_gui_picture
      IMPORTING
          mouse_pos_x
          mouse_pos_y
          sender.

    CLASS-METHODS: on_create_context_menu FOR EVENT context_menu OF cl_gui_picture
      IMPORTING
          sender.

    CLASS-METHODS: on_context_menu_selection FOR EVENT context_menu_selected OF cl_gui_picture
      IMPORTING
          fcode
          sender.
ENDCLASS.

CLASS lcl_events IMPLEMENTATION.

  METHOD on_picture_dblclick.

    MESSAGE |{ mouse_pos_x }{ mouse_pos_y }| TYPE 'I'.

  ENDMETHOD.

  METHOD on_create_context_menu.
    DATA(o_menu) = NEW cl_ctmenu( ).

    o_menu->add_function( fcode = 'FUNC1' text = 'Normal' ).
    o_menu->add_function( fcode = 'FUNC2' text = 'Center' ).

    sender->display_context_menu( context_menu = o_menu ).
  ENDMETHOD.

  METHOD on_context_menu_selection.

    CASE fcode.
      WHEN 'FUNC1'.
        sender->set_display_mode( display_mode = cl_gui_picture=>display_mode_normal ).
      WHEN 'FUNC2'.
        sender->set_display_mode( display_mode = cl_gui_picture=>display_mode_fit_center ).
    ENDCASE.

  ENDMETHOD.

ENDCLASS.

* Docking-Container für Bilddarstellung
DATA: o_dock TYPE REF TO cl_gui_docking_container.

* URL zur Google-API für die Erstellung des QR-Codes
PARAMETERS: p_url TYPE swk_url DEFAULT 'http://chart.apis.google.com/chart?chs=200x200&cht=qr&chld=|1&chl=viele%20lustige%20Zeichen/chart.png' LOWER CASE.

AT SELECTION-SCREEN OUTPUT.

  IF NOT o_dock IS BOUND.
* Dockingcontainer erzeugen
    o_dock = NEW #( repid = sy-repid
                    dynnr = sy-dynnr
                    side  = cl_gui_docking_container=>dock_at_bottom
                    ratio = 30 ).

* Bild über die URL laden und anzeigen
    DATA(o_pic) = NEW cl_gui_picture( parent = o_dock ).
    o_pic->set_display_mode( display_mode = cl_gui_picture=>display_mode_fit_center ).

    TRY.
* Eventhandler registrieren
        DATA: it_events TYPE cntl_simple_events.
        it_events = VALUE #( ( eventid = cl_gui_picture=>eventid_picture_dblclick
                               appl_event = abap_true )
                             ( eventid = cl_gui_picture=>eventid_context_menu
                               appl_event = abap_true )
                             ( eventid = cl_gui_picture=>eventid_context_menu_selected
                               appl_event = abap_true ) ).

        o_pic->set_registered_events( events = it_events ).

        SET HANDLER lcl_events=>on_picture_dblclick FOR o_pic.
        SET HANDLER lcl_events=>on_create_context_menu FOR o_pic.
        SET HANDLER lcl_events=>on_context_menu_selection FOR o_pic.

* Bild laden
        o_pic->load_picture_from_url_async( p_url ).

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

[ABAP] Docking Container (cl_gui_docking_container) maximiert darstellen

DATA: o_dock TYPE REF TO cl_gui_docking_container.
DATA: o_salv_ida TYPE REF TO if_salv_gui_table_ida.

PARAMETERS: p_name TYPE string. " Dummy-Parameter zum erzwingen des Selektionsbildes

AT SELECTION-SCREEN OUTPUT.

  IF NOT o_dock IS BOUND.
* maximierten Dockingcontainer auf dem Selektionsbild erzeugen
    o_dock = NEW #( repid     = sy-repid
                    dynnr     = sy-dynnr
                    side      = cl_gui_docking_container=>dock_at_bottom
                    extension = cl_gui_docking_container=>ws_maximizebox
*                    ratio     = 50
                  ).

* Testweise ein SALV TABLE IDA im Container einbetten
    o_salv_ida = cl_salv_gui_table_ida=>create( iv_table_name    = 'T100'
                                                io_gui_container = o_dock ).

  ENDIF.

[ABAP] GUI-Controls stapeln

* Quelle: https://www.tricktresor.de/blog/controls-stapeln/

DATA: it_mara TYPE STANDARD TABLE OF mara WITH DEFAULT KEY.
DATA: o_dock TYPE REF TO cl_gui_docking_container.
DATA: o_txt TYPE REF TO cl_gui_textedit.
DATA: o_alv TYPE REF TO cl_gui_alv_grid.

PARAMETERS: rb_txt RADIOBUTTON GROUP rbg DEFAULT 'X' USER-COMMAND rbc.
PARAMETERS: rb_alv RADIOBUTTON GROUP rbg.

INITIALIZATION.
  IF NOT o_dock IS BOUND.
* Containerobjekt erzeugen
    o_dock = NEW #( side  = cl_gui_docking_container=>dock_at_bottom
                    ratio = 90 ).

* Texteditor erzeugen
    o_txt = NEW #( parent = o_dock ).

* Daten für ALV holen
    SELECT *
      INTO TABLE @it_mara
      FROM mara
      UP TO 100 ROWS.

* ALV-Gitter erzeugen
    o_alv = NEW #( i_parent = o_dock ).
    o_alv->set_table_for_first_display( EXPORTING
                                          i_structure_name = 'MARA'
                                        CHANGING
                                          it_outtab = it_mara ).
  ENDIF.

AT SELECTION-SCREEN.
* wenn Radiobuttons geklickt
  IF sy-ucomm = 'RBC'.
* je nach Radiobutton die GUI-Controls ein-/ausblenden
    CASE abap_true.
      WHEN rb_txt.
        o_txt->set_visible( abap_true ).
        o_alv->set_visible( abap_false ).
      WHEN rb_alv.
        o_txt->set_visible( abap_false ).
        o_alv->set_visible( abap_true ).
    ENDCASE.
  ENDIF.

[ABAP] Bilder und Icons von einem Webserver (URL) anzeigen

Variante 1 (load_picture_from_url_async)

* Docking-Container für Bilddarstellung
DATA: o_dock TYPE REF TO cl_gui_docking_container.

PARAMETERS: p_url TYPE char255 DEFAULT 'http://url.de/1234.jpg' LOWER CASE.

AT SELECTION-SCREEN OUTPUT.

  IF NOT o_dock IS BOUND.
* Dockingcontainer erzeugen
    o_dock = NEW #( repid = sy-repid
                    dynnr = sy-dynnr
                    side  = cl_gui_docking_container=>dock_at_bottom
                    ratio = 30 ).

* Bild über die URL laden und anzeigen
    DATA(o_pic) = NEW cl_gui_picture( parent = o_dock ).
    o_pic->set_display_mode( display_mode = cl_gui_picture=>display_mode_fit_center ).

    TRY.
        o_pic->load_picture_from_url_async( p_url ).
      CATCH cx_root INTO DATA(e).
        MESSAGE e->get_text( ) TYPE 'S' DISPLAY LIKE 'E'.
    ENDTRY.
  ENDIF.

Variante 2 (load_picture_from_url mit Fehlerbehandlung)

* Docking-Container für Bilddarstellung
DATA: o_dock TYPE REF TO cl_gui_docking_container.

PARAMETERS: p_url TYPE char255 DEFAULT 'http://url.de/1234.jpg' LOWER CASE.

AT SELECTION-SCREEN OUTPUT.

  IF NOT o_dock IS BOUND.
* Dockingcontainer erzeugen
    o_dock = NEW #( repid = sy-repid
                    dynnr = sy-dynnr
                    side  = cl_gui_docking_container=>dock_at_bottom
                    ratio = 30 ).

* Bild über die URL laden und anzeigen
    DATA(o_pic) = NEW cl_gui_picture( parent = o_dock ).
    o_pic->set_display_mode( display_mode = cl_gui_picture=>display_mode_fit_center ).
    TRY.
        DATA(lv_load_ok) = 0.

* Bild laden
        o_pic->load_picture_from_url( EXPORTING url = p_url IMPORTING result = lv_load_ok ).

* Flush ist wichtig für die Abarbeitung des GUI-Queues, sonst gibt es einen Core-Dump -> "SYSTEM_POINTER_PENDING"
        cl_gui_cfw=>flush( ).

        CASE lv_load_ok.
          WHEN 0.
* Fehler
            MESSAGE 'Bild nicht vorhanden.' TYPE 'S' DISPLAY LIKE 'E'.
          WHEN 1.
* Ok
            MESSAGE 'Bild konnte geladen werden.' TYPE 'S' DISPLAY LIKE 'I'.
        ENDCASE.
      CATCH cx_root INTO DATA(e).
        MESSAGE e->get_text( ) TYPE 'S' DISPLAY LIKE 'E'.
    ENDTRY.

  ENDIF.

Variante 3 (load_picture_from_sap_icons)

* Docking-Container für Bilddarstellung
DATA: o_dock TYPE REF TO cl_gui_docking_container.

PARAMETERS: p_url TYPE char255 DEFAULT 'http://url.de/1234.jpg' LOWER CASE.

AT SELECTION-SCREEN OUTPUT.

  IF NOT o_dock IS BOUND.
* Dockingcontainer erzeugen
    o_dock = NEW #( repid = sy-repid
                    dynnr = sy-dynnr
                    side  = cl_gui_docking_container=>dock_at_bottom
                    ratio = 30 ).

* Bild über die URL laden und anzeigen
    DATA(o_pic) = NEW cl_gui_picture( parent = o_dock ).
    o_pic->set_display_mode( display_mode = cl_gui_picture=>display_mode_fit_center ).

    TRY.
        o_pic->load_picture_from_sap_icons( icon_annotation ).
      CATCH cx_root INTO DATA(e).
        MESSAGE e->get_text( ) TYPE 'S' DISPLAY LIKE 'E'.
    ENDTRY.
  ENDIF.

[ABAP] HTML-Code aus interner Tabelle generieren

CLASS lcl_itab_to_html DEFINITION FINAL.
  PUBLIC SECTION.
    TYPES: BEGIN OF ty_fields,
             field TYPE fieldname,
             width TYPE char20,
             text  TYPE char80,
           END OF ty_fields.

    TYPES: ty_it_fields TYPE STANDARD TABLE OF ty_fields WITH DEFAULT KEY.

    CLASS-METHODS:
      convert_itab_to_html_table
        IMPORTING
                  i_fields       TYPE ty_it_fields
                  i_itab         TYPE STANDARD TABLE
        RETURNING VALUE(rv_html) TYPE html_table.

ENDCLASS.

CLASS lcl_itab_to_html IMPLEMENTATION.
  METHOD convert_itab_to_html_table.

    APPEND '<table style="width: 100%; background: #ffffff; word-wrap: break-word; table-layout: fixed; font-family: Courier; font-size: 12px;">' TO rv_html.
    APPEND '  <thead>' TO rv_html.
    APPEND '    <tr>' TO rv_html.

    LOOP AT i_fields ASSIGNING FIELD-SYMBOL(<field>).
      IF <field>-width IS INITIAL.
        APPEND |      <th style="background: #eeeeee;"> { <field>-text }</th>| TO rv_html.
      ELSE.
        APPEND |      <th style="background: #eeeeee; width: { <field>-width };"> { <field>-text }</th>| TO rv_html.
      ENDIF.
    ENDLOOP.

    APPEND '    </tr>' TO rv_html.
    APPEND '  </thead>' TO rv_html.
    APPEND '  <tbody>' TO rv_html.

    FIELD-SYMBOLS: <value> TYPE any.

    LOOP AT i_itab ASSIGNING FIELD-SYMBOL(<data_line>).

      APPEND '    <tr>' TO rv_html.

      LOOP AT i_fields ASSIGNING FIELD-SYMBOL(<field_b>).
        ASSIGN COMPONENT <field_b>-field OF STRUCTURE <data_line> TO <value>.
        IF <value> IS ASSIGNED.
          APPEND |      <td>{ <value> }</td>| TO rv_html.
        ENDIF.
      ENDLOOP.

      APPEND '    </tr>' TO rv_html.
    ENDLOOP.

    APPEND '  </tbody>' TO rv_html.
    APPEND '</table>' TO rv_html.

  ENDMETHOD.

ENDCLASS.

START-OF-SELECTION.
* HTML-Viewer
  DATA(o_html) = NEW cl_gui_html_viewer( parent = cl_gui_docking_container=>default_screen ).

  DATA: it_mara TYPE STANDARD TABLE OF marav WITH DEFAULT KEY.

  SELECT * FROM marav INTO TABLE @it_mara.

  IF sy-subrc = 0.
* Felder für die Anzeige konfigurieren
    DATA(it_fields) = VALUE lcl_itab_to_html=>ty_it_fields( ( text  = 'Materialnummer'
                                                              field = 'MATNR'
                                                              width = '20%' )

                                                            ( text  = 'Kurztext'
                                                              field = 'MAKTX'
                                                              width = '20%' )

                                                            ( text  = 'Materialart'
                                                              field = 'MTART'
                                                              width = '20%' )

                                                            ( text  = 'Materialklasse'
                                                              field = 'MATKL'
                                                              width = '20%' )

                                                            ( text  = 'Mengeneinheit'
                                                              field = 'MEINS'
                                                              width = '10%' )

                                                            ( text  = 'Löschkennzeichen'
                                                              field = 'LVORM'
                                                              width = '10%' ) ).


* HTML aus den Quelldaten erzeugen
    DATA(it_html) = lcl_itab_to_html=>convert_itab_to_html_table( i_fields = it_fields
                                                                  i_itab   = it_mara ).

* URL zu HTML holen
    DATA: lv_url TYPE swk_url.

    o_html->load_data( IMPORTING
                         assigned_url = lv_url
                       CHANGING
                         data_table   = it_html ).

* HTML anzeigen
    o_html->show_url( url = lv_url ).

* leere SAP-Toolbar ausblenden
    cl_abap_list_layout=>suppress_toolbar( ).

* cl_gui_docking_container=>default_screen erzwingen
    WRITE: space.

  ENDIF.

[ABAP] Externe Webseite (HTML) anzeigen

TYPES: ty_it_events TYPE STANDARD TABLE OF cntl_simple_event WITH DEFAULT KEY.

PARAMETERS: p_url TYPE string LOWER CASE DEFAULT 'http://www.google.de'.

CLASS lcl_events DEFINITION.
  PUBLIC SECTION.

    CLASS-METHODS:
      on_navigate_complete FOR EVENT navigate_complete OF cl_gui_html_viewer
        IMPORTING
            url
            sender.

    CLASS-METHODS:
      on_sapevent FOR EVENT sapevent OF cl_gui_html_viewer
        IMPORTING
            action
            frame
            getdata
            postdata
            query_table
            sender.
ENDCLASS.

CLASS lcl_events IMPLEMENTATION.

* nach Aufbau des Dokuments
  METHOD on_navigate_complete.
    MESSAGE |Loaded: { url }| TYPE 'S'.
  ENDMETHOD.

* Link- oder Button-Klick
  METHOD on_sapevent.
    MESSAGE |Action: { action }, get: { getdata }| TYPE 'S'.
  ENDMETHOD.
ENDCLASS.

INITIALIZATION.

  DATA(o_dock) = NEW cl_gui_docking_container( ratio = 80
                                               side = cl_gui_docking_container=>dock_at_bottom
                                               no_autodef_progid_dynnr = 'X' ).

* HTML-Viewer
  DATA(o_html) = NEW cl_gui_html_viewer( parent = o_dock ).

* Eventtypten müssen gesondert registriert werden
  DATA(it_events) = VALUE ty_it_events( ( eventid = cl_gui_html_viewer=>m_id_navigate_complete
                                          appl_event = abap_true )
                                        ( eventid = cl_gui_html_viewer=>m_id_sapevent
                                          appl_event = abap_true ) ).

  o_html->set_registered_events( events = it_events ).

* Eventhandler registrieren
  SET HANDLER lcl_events=>on_navigate_complete FOR o_html.
  SET HANDLER lcl_events=>on_sapevent FOR o_html.

* HTML anzeigen
  o_html->show_url( url = |{ p_url }| ).

[ABAP] ALV-Grid als Property-Grid (Parametertabelle) mit Edit-Feldern und Typprüfung

Quelle / Inspiration gefunden auf: www.tricktresor.de

* ALV-Konstanten
INCLUDE <cl_alv_control>.

CLASS lcl_main DEFINITION.
  PUBLIC SECTION.

    TYPES: ty_enum TYPE i.

    TYPES: BEGIN OF ty_param,
             name  TYPE string,
             type  TYPE ty_enum,
             text  TYPE string,
             value TYPE string,
           END OF ty_param.

    TYPES: ty_it_params TYPE STANDARD TABLE OF ty_param WITH NON-UNIQUE DEFAULT KEY.

* Enum
    CLASS-DATA: string TYPE ty_enum VALUE 1 READ-ONLY.
    CLASS-DATA: int TYPE ty_enum VALUE 2 READ-ONLY.
    CLASS-DATA: float TYPE ty_enum VALUE 3 READ-ONLY.
    CLASS-DATA: date TYPE ty_enum VALUE 4 READ-ONLY.

* Bezeichner
    CONSTANTS: co_name TYPE string VALUE 'NAME'.
    CONSTANTS: co_type TYPE string VALUE 'TYPE'.
    CONSTANTS: co_text TYPE string VALUE 'TEXT'.
    CONSTANTS: co_value TYPE string VALUE 'VALUE'.

    METHODS: constructor
      IMPORTING
        o_parent TYPE REF TO cl_gui_container.

    METHODS: init_grid.

    METHODS: add_parameter
      IMPORTING
        parameter TYPE ty_param.

    METHODS: get_params
      RETURNING VALUE(rv_it_parameters) TYPE ty_it_params.

  PROTECTED SECTION.

    DATA: o_grid TYPE REF TO cl_gui_alv_grid.
    DATA: it_params TYPE ty_it_params.

    METHODS: on_data_changed FOR EVENT data_changed OF cl_gui_alv_grid
      IMPORTING
          er_data_changed
          sender.

ENDCLASS.

CLASS lcl_main IMPLEMENTATION.

  METHOD constructor.
    o_grid = NEW #( i_parent = o_parent ).
  ENDMETHOD.

* ALV-Gitter initialisieren
  METHOD init_grid.

    DATA(it_fieldcat) = VALUE lvc_t_fcat( ( fieldname  = co_name
                                            outputlen  = 15
                                            coltext    = 'Parameter'
                                            style      = alv_style_font_bold + alv_style_color_int_group )
                                          ( fieldname  = co_type
                                            outputlen  = 5
                                            coltext    = 'Type'
                                            no_out     = abap_true )
                                          ( fieldname  = co_text
                                            outputlen  = 15
                                            coltext    = 'Text' )
                                          ( fieldname  = co_value
                                            outputlen  = 20
                                            coltext    = 'Value'
                                            edit       = abap_true
                                            fix_column = abap_true ) ).

    DATA(s_layout) = VALUE lvc_s_layo( no_toolbar = abap_true
                                       no_headers = abap_false ).

    SET HANDLER on_data_changed FOR o_grid.

* Tastenevents registrieren
    o_grid->register_edit_event( i_event_id = cl_gui_alv_grid=>mc_evt_enter ).    " Enter
    o_grid->register_edit_event( i_event_id = cl_gui_alv_grid=>mc_evt_modified ). " Eingabe, Cursortasten

* ALV-Grid selektionsbereit setzen
    o_grid->set_ready_for_input( i_ready_for_input = 1 ).

    o_grid->set_table_for_first_display( EXPORTING
                                           is_layout       = s_layout
                                         CHANGING
                                           it_outtab       = it_params
                                           it_fieldcatalog = it_fieldcat ).

  ENDMETHOD.

* Parameterliste zurückholen
  METHOD get_params.
    rv_it_parameters = it_params.
  ENDMETHOD.

* Parameter hinzufügen
  METHOD add_parameter.
    APPEND VALUE #( name  = parameter-name
                    type  = parameter-type
                    text  = parameter-text
                    value = parameter-value ) TO it_params.
  ENDMETHOD.

  METHOD on_data_changed.
* geänderte Zellen durchgehen
    LOOP AT er_data_changed->mt_good_cells ASSIGNING FIELD-SYMBOL(<fs_changed>).
      IF <fs_changed> IS ASSIGNED.
* Zeile x aus der iTab it_params rausholen und daraus die Zelle anhand des Spaltennamens (Feldnamens) holen
        TRY.
            ASSIGN COMPONENT <fs_changed>-fieldname OF STRUCTURE it_params[ <fs_changed>-row_id ] TO FIELD-SYMBOL(<fs_param>).

            IF <fs_param> IS ASSIGNED.
* Änderungswert in die Zelle der iTab (it_params) rückschreiben
              CASE it_params[ <fs_changed>-row_id ]-type.
                WHEN lcl_main=>string.
                  <fs_param> = <fs_changed>-value.
                WHEN lcl_main=>int.
* Typprüfung für Int
                  IF cl_abap_matcher=>create( pattern = '^[-+]?[0-9]*$'
                                              text = <fs_changed>-value
                                              ignore_case = abap_true )->match( ) = abap_true.

                    <fs_param> = <fs_changed>-value.
                  ELSE.
* Eingabefehler im Protokoll anzeigen
                    er_data_changed->add_protocol_entry( i_msgid     = '0K'
                                                         i_msgno     = '000'
                                                         i_msgty     = 'E'
                                                         i_msgv1     = 'Ungültiger Wert:'
                                                         i_msgv2     = <fs_changed>-value
                                                         i_msgv3     = 'Bitte einen Wert vom Typ int eingeben!'
                                                         i_msgv4     = ''
                                                         i_fieldname = <fs_changed>-fieldname
                                                         i_row_id    = <fs_changed>-row_id ).
                  ENDIF.
                WHEN lcl_main=>float.
* Typprüfung für Float
                  IF cl_abap_matcher=>create( pattern = '^[-+]?[0-9]*[,]?[0-9]+([eE][-+]?[0-9]+)?$'
                                              text = <fs_changed>-value
                                              ignore_case = abap_true )->match( ) = abap_true.

                    <fs_param> = <fs_changed>-value.
                  ELSE.
* Eingabefehler im Protokoll anzeigen
                    er_data_changed->add_protocol_entry( i_msgid     = '0K'
                                                         i_msgno     = '000'
                                                         i_msgty     = 'E'
                                                         i_msgv1     = 'Ungültiger Wert:'
                                                         i_msgv2     = <fs_changed>-value
                                                         i_msgv3     = 'Bitte einen Wert vom Typ float eingeben!'
                                                         i_msgv4     = ''
                                                         i_fieldname = <fs_changed>-fieldname
                                                         i_row_id    = <fs_changed>-row_id ).
                  ENDIF.
                WHEN lcl_main=>date.
* Typprüfung für Date
                  IF cl_abap_matcher=>create( pattern = '^(0[1-9]|[12][0-9]|3[01])[- /.](0[1-9]|1[012])[- /.](19|20)\d\d$'
                                              text = <fs_changed>-value
                                              ignore_case = abap_true )->match( ) = abap_true.

                    <fs_param> = <fs_changed>-value.
                  ELSE.
* Eingabefehler im Protokoll anzeigen
                    er_data_changed->add_protocol_entry( i_msgid     = '0K'
                                                         i_msgno     = '000'
                                                         i_msgty     = 'E'
                                                         i_msgv1     = 'Ungültiger Wert:'
                                                         i_msgv2     = <fs_changed>-value
                                                         i_msgv3     = 'Bitte einen Datumswert im Format dd.mm.yyyy eingeben!'
                                                         i_msgv4     = ''
                                                         i_fieldname = <fs_changed>-fieldname
                                                         i_row_id    = <fs_changed>-row_id ).
                  ENDIF.
              ENDCASE.
            ENDIF.
          CATCH cx_root.
        ENDTRY.
      ENDIF.
    ENDLOOP.

  ENDMETHOD.

ENDCLASS.

**********************************************************************
*
* Datentypen, Variablen, Konstanten
*
**********************************************************************
DATA: o_main TYPE REF TO lcl_main.

**********************************************************************
*
* SELECTION-SCREEN
*
**********************************************************************
SELECTION-SCREEN BEGIN OF SCREEN 2000.
SELECTION-SCREEN END OF SCREEN 2000.

**********************************************************************
*
* INITIALIZATION
*
**********************************************************************
INITIALIZATION.

  o_main = NEW #( o_parent = NEW cl_gui_docking_container( side = cl_gui_docking_container=>dock_at_left
                                                           extension = 500
                                                           no_autodef_progid_dynnr = abap_true ) ).

* Beispiel-Parameter einfügen
* String-Parameter
  o_main->add_parameter( VALUE #( name = 'PERSON_VOR'
                                  type = lcl_main=>string
                                  text = 'Vorname'
                                  value = 'Udo' ) ).
* String-Parameter
  o_main->add_parameter( VALUE #( name = 'PERSON_NACH'
                                  type = lcl_main=>string
                                  text = 'Nachname'
                                  value = 'Lehmann' ) ).
* Int-Parameter
  o_main->add_parameter( VALUE #( name = 'PERSON_ALTER'
                                  type = lcl_main=>int
                                  text = 'Alter'
                                  value = '34' ) ).
* Float-Parameter
  o_main->add_parameter( VALUE #( name = 'PERSON_GROESSE'
                                  type = lcl_main=>float
                                  text = 'Größe'
                                  value = '1,80' ) ).
* Date-Parameter
  o_main->add_parameter( VALUE #( name = 'PERSON_DATE'
                                  type = lcl_main=>date
                                  text = 'Geburtsdatum'
                                  value = '01.01.1980' ) ).

**********************************************************************
*
* AT SELECTION-SCREEN OUTPUT
*
**********************************************************************
AT SELECTION-SCREEN OUTPUT.

  IF o_main IS BOUND.
    o_main->init_grid( ).
  ENDIF.

**********************************************************************
*
* AT SELECTION-SCREEN
*
**********************************************************************
AT SELECTION-SCREEN.
* wenn "Ausführen" (F8) geklickt wurde
  IF sy-ucomm = 'CRET'.
    cl_demo_output=>display_data( o_main->get_params( ) ).
  ENDIF.

**********************************************************************
*
* START-OF-SELECTION
*
**********************************************************************
START-OF-SELECTION.
* leeres Selektionbild 2000 anzeigen
  CALL SELECTION-SCREEN 2000.

[ABAP] ALV-Grid als Property-Grid mit Tri-State Klickfeldern/Buttons (ON / OFF / UNDEF)

Quelle / Inspiration gefunden auf: www.tricktresor.de

Die Codeteile mit UNDEF / abap_undefined können auch auskommentiert werden, so dass sich eine Möglichkeit der Dual-State Umschaltung (ON / OFF) per Mausklick ergibt.

* ALV-Konstanten
INCLUDE <cl_alv_control>.

CLASS lcl_main DEFINITION.
  PUBLIC SECTION.

    TYPES: BEGIN OF ty_param,
             name   TYPE string,
             text   TYPE string,
             status TYPE boolean,
           END OF ty_param.

    TYPES: ty_it_params TYPE STANDARD TABLE OF ty_param WITH NON-UNIQUE DEFAULT KEY.

    TYPES: BEGIN OF ty_ui_param,
             name    TYPE string,
             text    TYPE string,
             status  TYPE icon_text,
             t_color TYPE lvc_t_scol,
             t_style TYPE lvc_t_styl,
           END OF ty_ui_param.

    TYPES: ty_it_ui_params TYPE STANDARD TABLE OF ty_ui_param.

    TYPES: ty_cell_type TYPE i.

    CONSTANTS: co_celltype_hotspot TYPE ty_cell_type VALUE 1.
    CONSTANTS: co_celltype_button TYPE ty_cell_type VALUE 2.

* Farben
    CONSTANTS: co_color_on TYPE i VALUE col_positive.
    CONSTANTS: co_color_off TYPE i VALUE col_negative.
    CONSTANTS: co_color_undef TYPE i VALUE col_total.

* Bezeichner
    CONSTANTS: co_status TYPE string VALUE 'STATUS'.
    CONSTANTS: co_on TYPE string VALUE 'ON'.
    CONSTANTS: co_off TYPE string VALUE 'OFF'.
    CONSTANTS: co_undef TYPE string VALUE 'N/A'.

* Icons
    CONSTANTS status_icon_on TYPE icon_text VALUE icon_oo_object.
    CONSTANTS status_icon_off TYPE icon_text VALUE icon_system_start_recording.
    CONSTANTS status_icon_undef TYPE icon_text VALUE icon_oo_class.
*    CONSTANTS status_icon_undef TYPE icon_text VALUE icon_led_yellow.

    METHODS: constructor
      IMPORTING
        o_parent TYPE REF TO cl_gui_container.

    METHODS: init_grid
      IMPORTING
        cell_type TYPE ty_cell_type.

    METHODS: add_parameter
      IMPORTING
        parameter TYPE ty_param.

    METHODS: get_params
      RETURNING VALUE(rv_it_parameters) TYPE ty_it_params.

  PROTECTED SECTION.

    DATA: o_grid TYPE REF TO cl_gui_alv_grid.
    DATA: it_params TYPE ty_it_params.
    DATA: it_ui_params TYPE ty_it_ui_params.

    METHODS: set_color
      IMPORTING
                status       TYPE boolean
      RETURNING VALUE(color) TYPE lvc_t_scol.

    METHODS: on_hotspot_click FOR EVENT hotspot_click OF cl_gui_alv_grid
      IMPORTING
          e_row_id.

    METHODS: on_button_click FOR EVENT button_click OF cl_gui_alv_grid
      IMPORTING
          es_col_id
          es_row_no.

ENDCLASS.

CLASS lcl_main IMPLEMENTATION.

  METHOD constructor.
    o_grid = NEW #( i_parent = o_parent ).
  ENDMETHOD.

  METHOD init_grid.

    CLEAR: it_ui_params.

* Parameter in ALV-Zeilen umwandeln
    LOOP AT it_params ASSIGNING FIELD-SYMBOL(<fs_param>).

      CASE <fs_param>-status.
        WHEN abap_true.
* ON
          APPEND VALUE #( name = <fs_param>-name
                          text = <fs_param>-text
                          status = |{ status_icon_on } { co_on }|
                          t_color = me->set_color( abap_true ) ) TO it_ui_params.
        WHEN abap_false.
* OFF
          APPEND VALUE #( name = <fs_param>-name
                          text = <fs_param>-text
                          status = |{ status_icon_off } { co_off }|
                          t_color = me->set_color( abap_false ) ) TO it_ui_params.
        WHEN abap_undefined.
* UNDEF
          APPEND VALUE #( name = <fs_param>-name
                          text = <fs_param>-text
                          status = |{ status_icon_undef } { co_undef }|
                          t_color = me->set_color( abap_undefined ) ) TO it_ui_params.

      ENDCASE.

    ENDLOOP.

    DATA: it_fieldcat TYPE lvc_t_fcat.

    IF cell_type = co_celltype_button.
      it_fieldcat = VALUE lvc_t_fcat( ( fieldname = 'NAME'
                                        outputlen = 15
                                        coltext = 'Parameter'
                                        style = alv_style_font_bold + alv_style_color_int_group )
                                      ( fieldname = 'TEXT'
                                        outputlen = 20
                                        coltext = 'Description' )
                                      ( fieldname = co_status
                                        outputlen = 10
                                        coltext = 'Switch'
                                        style = alv_style_button
                                        icon = abap_true
                                        fix_column = abap_true ) ).
    ELSE.
      it_fieldcat = VALUE lvc_t_fcat( ( fieldname = 'NAME'
                                        outputlen = 15
                                        coltext = 'Parameter'
                                        style = alv_style_font_bold + alv_style_color_int_group )
                                      ( fieldname = 'TEXT'
                                        outputlen = 20
                                        coltext = 'Description' )
                                      ( fieldname = co_status
                                        outputlen = 10
                                        coltext = 'Switch'
                                        hotspot = abap_true
                                        icon = abap_true
                                        fix_column = abap_true ) ).
    ENDIF.

    DATA(s_layout) = VALUE lvc_s_layo( stylefname = 'T_STYLE'
                                       ctab_fname = 'T_COLOR'
                                       no_toolbar = abap_true
                                       no_headers = abap_false ).

    SET HANDLER on_hotspot_click FOR o_grid.
    SET HANDLER on_button_click FOR o_grid.

    o_grid->set_table_for_first_display( EXPORTING
                                           is_layout = s_layout
                                         CHANGING
                                           it_outtab = it_ui_params
                                           it_fieldcatalog = it_fieldcat ).

  ENDMETHOD.

* Parameterliste zurückholen
  METHOD get_params.
    rv_it_parameters = it_params.
  ENDMETHOD.

* Parameter hinzufügen
  METHOD add_parameter.
    APPEND VALUE #( name   = parameter-name
                    text   = parameter-text
                    status = parameter-status ) TO it_params.
  ENDMETHOD.

* Hintergrundfarben setzen
  METHOD set_color.

    CASE status.
      WHEN abap_true.
* Grün / ON
        color = VALUE #( ( fname = co_status color-col = co_color_on ) ).
      WHEN abap_false.
* Rot / OFF
        color = VALUE #( ( fname = co_status color-col = co_color_off ) ).
      WHEN abap_undefined.
* Gelb / UNDEF
        color = VALUE #( ( fname = co_status color-col = co_color_undef ) ).
    ENDCASE.

  ENDMETHOD.

  METHOD on_hotspot_click.

* geklickte ALV-Zeile holen
    READ TABLE it_ui_params ASSIGNING FIELD-SYMBOL(<ui_param>) INDEX e_row_id-index.
* korrespondierenden Parameter ermitteln
    READ TABLE it_params ASSIGNING FIELD-SYMBOL(<param>) WITH KEY name = <ui_param>-name.

    CASE <param>-status.
      WHEN abap_true.
* ON->OFF
        <ui_param>-status = |{ status_icon_off } { co_off }|.
        <ui_param>-t_color = me->set_color( abap_false ).
        <param->-status = abap_false.
      WHEN abap_false.
* OFF->UNDEF
        <ui_param>-status = |{ status_icon_undef } { co_undef }|.
        <ui_param>-t_color = me->set_color( abap_undefined ).
        <param>-status = abap_undefined.
      WHEN abap_undefined.
* UNDEF->ON
        <ui_param>-status = |{ status_icon_on } { co_on }|.
        <ui_param>-t_color = me->set_color( abap_true ).
        <param>-status = abap_true.
    ENDCASE.

    o_grid->refresh_table_display( is_stable = VALUE lvc_s_stbl( row = abap_true
                                                                 col = abap_true )
                                   i_soft_refresh = abap_false ).
  ENDMETHOD.

  METHOD on_button_click.
* geklickte ALV-Zeile holen
    READ TABLE it_ui_params ASSIGNING FIELD-SYMBOL(<ui_param>) INDEX es_row_no-row_id.
* korrespondierenden Parameter ermitteln
    READ TABLE it_params ASSIGNING FIELD-SYMBOL(<param>) WITH KEY name = <ui_param>-name.

    CASE <param>-status.
      WHEN abap_true.
* ON->OFF
        <ui_param>-status = status_icon_off.
        <ui_param>-t_color = me->set_color( abap_false ).
        <param>-status = abap_false.
      WHEN abap_false.
* OFF->UNDEF
        <ui_param>-status = status_icon_undef.
        <ui_param>-t_color = me->set_color( abap_undefined ).
        <param>-status = abap_undefined.
      WHEN abap_undefined.
* UNDEF->ON
        <ui_param>-status = status_icon_on.
        <ui_param>-t_color = me->set_color( abap_true ).
        <param>-status = abap_true.
    ENDCASE.

    o_grid->refresh_table_display( is_stable = VALUE lvc_s_stbl( row = abap_true
                                                                 col = abap_true )
                                   i_soft_refresh = abap_false ).
  ENDMETHOD.


ENDCLASS.

**********************************************************************
*
* Datentypen, Variablen, Konstanten
*
**********************************************************************
DATA: o_main TYPE REF TO lcl_main.

**********************************************************************
*
* SELECTION-SCREEN
*
**********************************************************************
SELECTION-SCREEN BEGIN OF SCREEN 2000.
SELECTION-SCREEN END OF SCREEN 2000.

**********************************************************************
*
* INITIALIZATION
*
**********************************************************************
INITIALIZATION.

  o_main = NEW #( o_parent = NEW cl_gui_docking_container( side = cl_gui_docking_container=>dock_at_right
                                                           extension = 400
                                                           no_autodef_progid_dynnr = abap_true ) ).

  o_main->add_parameter( VALUE #( name = 'SHOW_RESULT' text = 'Ergebnisse anzeigen' status = abap_true ) ).
  o_main->add_parameter( VALUE #( name = 'HIDE_COLS' text = 'Spalten ausblenden' status = abap_false ) ).
  o_main->add_parameter( VALUE #( name = 'DELETE_ON_EXIT' text = 'Beim Beenden löschen' status = abap_undefined ) ).

**********************************************************************
*
* AT SELECTION-SCREEN OUTPUT
*
**********************************************************************
AT SELECTION-SCREEN OUTPUT.

  IF o_main IS BOUND.
* Flag cell_type triggert den Typ (Hotspot / Button) des Klick-Feldes
    o_main->init_grid( cell_type = lcl_main=>co_celltype_hotspot ).
  ENDIF.

**********************************************************************
*
* AT SELECTION-SCREEN
*
**********************************************************************
AT SELECTION-SCREEN.
* wenn "Ausführen" (F8) geklickt wurde
  IF sy-ucomm = 'CRET'.
    cl_demo_output=>display_data( o_main->get_params( ) ).
  ENDIF.

**********************************************************************
*
* START-OF-SELECTION
*
**********************************************************************
START-OF-SELECTION.
* leeres Selektionbild 2000 anzeigen
  CALL SELECTION-SCREEN 2000.