[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.

[ABAP] Baumstruktur mit Hilfe des cl_gui_list_tree anzeigen, Events abfangen

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

DATA: it_nodes TYPE treev_ntab.
DATA: it_items TYPE STANDARD TABLE OF mtreeitm WITH DEFAULT KEY.

CLASS lcl_event DEFINITION.
  PUBLIC SECTION.
    CLASS-METHODS: on_node_double_click FOR EVENT node_double_click OF cl_gui_list_tree
      IMPORTING
          node_key.
    CLASS-METHODS: on_expand_no_children FOR EVENT expand_no_children OF cl_gui_list_tree
      IMPORTING
          node_key.
    CLASS-METHODS: on_item_double_click FOR EVENT item_double_click OF cl_gui_list_tree
      IMPORTING
          node_key
          item_name.
    CLASS-METHODS: on_button_click FOR EVENT button_click OF cl_gui_list_tree
      IMPORTING
          node_key
          item_name.
    CLASS-METHODS: on_link_click FOR EVENT link_click OF cl_gui_list_tree
      IMPORTING
          node_key
          item_name.
    CLASS-METHODS: on_checkbox_change FOR EVENT checkbox_change OF cl_gui_list_tree
      IMPORTING
          node_key
          item_name
          checked.
ENDCLASS.

CLASS lcl_event IMPLEMENTATION.
  METHOD on_node_double_click.
    WRITE: / |Node double click on node: { node_key }|.
  ENDMETHOD.

  METHOD on_item_double_click.
    WRITE: / |Item double click on node: { node_key }, item: { item_name }|.
  ENDMETHOD.

  METHOD on_link_click.
    WRITE: / |Link click on node: { node_key }, item: { item_name }|.
  ENDMETHOD.

  METHOD on_button_click.
    WRITE: / |Button click on node: { node_key }, item: { item_name }|.
  ENDMETHOD.

  METHOD on_checkbox_change.
    WRITE: / |Checkbox change on node: { node_key }, item: { item_name }|.
  ENDMETHOD.

  METHOD on_expand_no_children.
    WRITE: / |Expand no children on node: { node_key }|.
  ENDMETHOD.
ENDCLASS.

START-OF-SELECTION.

* Container-Objekt erzeugen
  DATA(o_dock) = NEW cl_gui_docking_container( no_autodef_progid_dynnr = abap_true
                                               side = cl_gui_docking_container=>dock_at_left
                                               ratio = 20
                                               caption = 'Datenausgabe' ).

* Tree-Objekt erzeugen
  DATA(o_tree) = NEW cl_gui_list_tree( parent = o_dock
                                       node_selection_mode = cl_gui_list_tree=>node_sel_mode_single
                                       item_selection = abap_true
                                       with_headers = abap_false ).

* Eventtypten müssen gesondert registriert werden
  DATA(it_events) = VALUE ty_it_events( ( eventid    = cl_gui_list_tree=>eventid_node_double_click
                                          appl_event = abap_true )
                                        ( eventid    = cl_gui_list_tree=>eventid_item_double_click
                                          appl_event = abap_true )
                                        ( eventid    = cl_gui_list_tree=>eventid_expand_no_children
                                          appl_event = abap_true )
                                        ( eventid    = cl_gui_list_tree=>eventid_link_click
                                          appl_event = abap_true )
                                        ( eventid    = cl_gui_list_tree=>eventid_button_click
                                          appl_event = abap_true )
                                        ( eventid    = cl_gui_list_tree=>eventid_checkbox_change
                                          appl_event = abap_true ) ).

  o_tree->set_registered_events( events = it_events ).

  SET HANDLER lcl_event=>on_node_double_click FOR o_tree.
  SET HANDLER lcl_event=>on_item_double_click FOR o_tree.
  SET HANDLER lcl_event=>on_expand_no_children FOR o_tree.
  SET HANDLER lcl_event=>on_link_click FOR o_tree.
  SET HANDLER lcl_event=>on_button_click FOR o_tree.
  SET HANDLER lcl_event=>on_checkbox_change FOR o_tree.

* Tree-Nodes einfügen -> die Bezeichner müssen eindeutig sein
  it_nodes = VALUE #( ( node_key  = 'ROOT'
                        hidden    = abap_false
                        disabled  = abap_false
                        isfolder  = abap_true )

                      ( node_key  = 'NODE1'
                        relatkey  = 'ROOT'
                        relatship = cl_gui_list_tree=>relat_last_child
                        hidden    = abap_false
                        disabled  = abap_false
                        isfolder  = abap_true )

                      ( node_key  = 'NODE1_1'
                        relatkey  = 'NODE1'
                        relatship = cl_gui_list_tree=>relat_last_child
                        hidden    = abap_false
                        disabled  = abap_false
                        isfolder  = abap_false )

                      ( node_key  = 'NODE1_2'
                        relatkey  = 'NODE1'
                        relatship = cl_gui_list_tree=>relat_last_child
                        hidden    = abap_false
                        disabled  = abap_false
                        isfolder  = abap_false )

                      ( node_key  = 'NODE1_3'
                        relatkey  = 'NODE1'
                        relatship = cl_gui_list_tree=>relat_last_child
                        hidden    = abap_false
                        disabled  = abap_false
                        isfolder  = abap_false )

                      ( node_key  = 'NODE2'
                        relatkey  = 'ROOT'
                        relatship = cl_gui_list_tree=>relat_last_child
                        hidden    = abap_false
                        disabled  = abap_false
                        isfolder  = abap_false )

                      ( node_key  = 'NODE3'
                        relatkey  = 'ROOT'
                        relatship = cl_gui_list_tree=>relat_last_child
                        hidden    = abap_false
                        disabled  = abap_false
                        isfolder  = abap_false ) ).

* Items für die Nodes definieren
  it_items = VALUE #( ( node_key  = 'ROOT'
                        item_name = '1'
                        style     = cl_gui_list_tree=>style_default
                        class     = cl_gui_list_tree=>item_class_text
                        alignment = cl_gui_list_tree=>align_auto
                        font      = cl_gui_list_tree=>item_font_fixed
                        text      = 'Root'
                        t_image   = icon_led_green )
* Ordner
                      ( node_key  = 'NODE1'
                        item_name = '1'
                        style     = cl_gui_list_tree=>style_default
                        class     = cl_gui_list_tree=>item_class_text
                        alignment = cl_gui_list_tree=>align_auto
                        font      = cl_gui_list_tree=>item_font_fixed
                        text      = 'Node 1'
                        t_image   = icon_led_yellow )
* Item Button
                      ( node_key  = 'NODE1_1'
                        item_name = '1'
                        style     = cl_gui_list_tree=>style_default
                        class     = cl_gui_list_tree=>item_class_button
                        alignment = cl_gui_list_tree=>align_auto
                        font      = cl_gui_list_tree=>item_font_fixed
                        text      = 'Node 1_1'
                        t_image   = icon_led_green )
* Item Checkbox
                      ( node_key  = 'NODE1_2'
                        item_name = '1'
                        style     = cl_gui_list_tree=>style_default
                        class     = cl_gui_list_tree=>item_class_checkbox
                        alignment = cl_gui_list_tree=>align_auto
                        font      = cl_gui_list_tree=>item_font_fixed
                        text      = 'Node 1_2'
                        t_image   = icon_led_green
                        editable  = abap_true )
* Item Link
                      ( node_key  = 'NODE1_3'
                        item_name = '1'
                        style     = cl_gui_list_tree=>style_default
                        class     = cl_gui_list_tree=>item_class_link
                        alignment = cl_gui_list_tree=>align_auto
                        font      = cl_gui_list_tree=>item_font_fixed
                        text      = 'Node 1_3'
                        t_image   = icon_led_green )
* Item mit 4 Spalten
                      ( node_key   = 'NODE2'
                        item_name  = '1'
                        style      = cl_gui_list_tree=>style_default
                        class      = cl_gui_list_tree=>item_class_text
                        alignment  = cl_gui_list_tree=>align_auto
                        font       = cl_gui_list_tree=>item_font_fixed
                        text       = ''
                        t_image    = icon_led_green
                        usebgcolor = abap_true )

                      ( node_key   = 'NODE2'
                        item_name  = '2'
                        style      = cl_gui_list_tree=>style_default
                        class      = cl_gui_list_tree=>item_class_text
                        alignment  = cl_gui_list_tree=>align_left
                        font       = cl_gui_list_tree=>item_font_fixed
                        length     = 4
                        text       = '1000'
                        usebgcolor = abap_true )

                      ( node_key   = 'NODE2'
                        item_name  = '3'
                        style      = cl_gui_list_tree=>style_default
                        class      = cl_gui_list_tree=>item_class_text
                        alignment  = cl_gui_list_tree=>align_left
                        font       = cl_gui_list_tree=>item_font_fixed
                        length     = 10
                        text       = 'Liter'
                        usebgcolor = abap_true )

                      ( node_key   = 'NODE2'
                        item_name  = '4'
                        style      = cl_gui_list_tree=>style_default
                        class      = cl_gui_list_tree=>item_class_text
                        alignment  = cl_gui_list_tree=>align_auto
                        font       = cl_gui_list_tree=>item_font_prop
                        text       = 'Testeintrag 1' )
* Item mit 4 Spalten
                      ( node_key   = 'NODE3'
                        item_name  = '1'
                        style      = cl_gui_list_tree=>style_default
                        class      = cl_gui_list_tree=>item_class_text
                        alignment  = cl_gui_list_tree=>align_auto
                        font       = cl_gui_list_tree=>item_font_fixed
                        text       = ''
                        t_image    = icon_led_green
                        usebgcolor = abap_true )

                      ( node_key   = 'NODE3'
                        item_name  = '2'
                        style      = cl_gui_list_tree=>style_default
                        class      = cl_gui_list_tree=>item_class_text
                        alignment  = cl_gui_list_tree=>align_left
                        font       = cl_gui_list_tree=>item_font_fixed
                        length     = 4
                        text       = '0100'
                        usebgcolor = abap_true )

                      ( node_key   = 'NODE3'
                        item_name  = '3'
                        style      = cl_gui_list_tree=>style_default
                        class      = cl_gui_list_tree=>item_class_text
                        alignment  = cl_gui_list_tree=>align_left
                        font       = cl_gui_list_tree=>item_font_fixed
                        length     = 10
                        text       = 'mm'
                        usebgcolor = abap_true )

                      ( node_key   = 'NODE3'
                        item_name  = '4'
                        style      = cl_gui_list_tree=>style_default
                        class      = cl_gui_list_tree=>item_class_text
                        alignment  = cl_gui_list_tree=>align_auto
                        font       = cl_gui_list_tree=>item_font_prop
                        text       = 'Testeintrag 2' ) ).

  o_tree->add_nodes_and_items( node_table                = it_nodes
                               item_table                = it_items
                               item_table_structure_name = 'MTREEITM' ). " Typ muss gleich mit Zeilentyp von it_items sein

* Root-Nodes des Trees expandieren
  o_tree->expand_root_nodes( ).

* leere Toolbar ausblenden
  cl_abap_list_layout=>suppress_toolbar( ).

  WRITE space. " wichtig für Erzwingung der Listenausgabe und Anzeige des Trees

Weiterführende Infos: Link und Link