[ABAP] ALV-Grid: Bei Refresh Cursor- und Scrollposition halten

Variante 1 ( refresh_table_display )

DATA: o_alv TYPE REF TO cl_gui_alv_grid.
  
...

DATA: lv_stable TYPE lvc_s_stbl.
lv_stable-row = 'X'.
lv_stable-col = 'X'.

o_alv->refresh_table_display( is_stable = lv_stable ).

Variante 2 ( set_scroll_info_via_id, set_current_cell_via_id )

DATA: o_alv TYPE REF TO cl_gui_alv_grid.
  
...

* Scrollbalken und Cursorposition im Gitter auslesen
DATA: lv_row_no TYPE lvc_s_roid.
DATA: lv_row_info TYPE lvc_s_row.
DATA: lv_col_info TYPE lvc_s_col.

o_alv->get_scroll_info_via_id( IMPORTING
                                 es_row_no   = lv_row_no
                                 es_row_info = lv_row_info
                                 es_col_info = lv_col_info ).

DATA: lv_row_no2 TYPE lvc_s_roid.
DATA: lv_row_id2 TYPE lvc_s_row.
DATA: lv_col_id2 TYPE lvc_s_col.

o_alv->get_current_cell( IMPORTING
                           es_row_id = lv_row_id2
                           es_col_id = lv_col_id2
                           es_row_no = lv_row_no2 ).
                           
o_alv->refresh_table_display( ).

* Scrollbalken und Cursorposition im Gitter auf die alte Position setzen
o_alv->set_scroll_info_via_id( is_row_info = lv_row_info
                               is_col_info = lv_col_info
                               is_row_no   = lv_row_no ).

o_alv->set_current_cell_via_id( is_row_id    = lv_row_id2
                                is_column_id = lv_col_id2
                                is_row_no    = lv_row_no2 ).

Weiterführende Infos: Link

[ABAP] ALV-Grid: Gitter-Zeile löschen

Variante 1 (Standard-Button)

-> Button cl_gui_alv_grid=>mc_fc_loc_delete_row muss in der Toolbar eingeblendet sein
-> die zugehörige interne Tabelle wird automatisch geupdated

Variante 2 (on_user_command)

* interne Tabelle it_itab muss global bekannt sein
METHOD on_user_command.
  CASE e_ucomm.
* Button-Kommando BTN_DEL_ROW abfangen
    WHEN 'BTN_DEL_ROW'.
      DATA: it_row_no TYPE lvc_t_roid.
      DATA: lv_flag TYPE boolean.

      sender->get_selected_rows( IMPORTING et_row_no = it_row_no ).

      IF lines( it_row_no ) > 0.
        SORT: it_row_no BY row_id.
        lv_flag = abap_false.

        LOOP AT it_row_no ASSIGNING FIELD-SYMBOL(<fs_row>).
          IF lv_flag = abap_false.
            DELETE it_itab INDEX <fs_row>-row_id.
            lv_flag = abap_true.
          ELSE.
            DELETE it_itab INDEX <fs_row>-row_id - 1.
          ENDIF.
        ENDLOOP.

        sender->refresh_table_display( ).
      ENDIF.
  ENDCASE.
ENDMETHOD.

[ABAP] ALV-Grid: Toolbar-Buttons entfernen

Variante 1 (Event on_toolbar)

* Die Button-Bezeichner sind Konstanten der Klasse cl_gui_alv_grid
METHOD on_toolbar.
* alle Toolbar-Buttons entfernen, außer
  DELETE e_object->mt_toolbar WHERE
        function NE cl_gui_alv_grid=>mc_fc_refresh          " Refresh
    AND function NE cl_gui_alv_grid=>mc_fc_loc_append_row   " Append
    AND function NE cl_gui_alv_grid=>mc_fc_loc_insert_row   " Insert
    AND function NE cl_gui_alv_grid=>mc_fc_loc_delete_row   " Delete
    AND function NE cl_gui_alv_grid=>mc_mb_export           " Excel
    AND function NE cl_gui_alv_grid=>mc_fc_current_variant. " Layout
ENDMETHOD.

Variante 2 (it_toolbar_excluding)

DATA: o_alv TYPE REF TO cl_gui_alv_grid.
DATA: it_tab TYPE STANDARD TABLE OF ...
DATA: it_fcat TYPE lvc_t_fcat.

...

* Liste mit auszuschließenden Toolbuttons erstellen
DATA(it_excl_toolbuttons) = VALUE ui_functions( ( cl_gui_alv_grid=>mc_fc_maximum )
                                                ( cl_gui_alv_grid=>mc_fc_minimum ) ).

* Layout anpassen
DATA(lv_layout) = VALUE lvc_s_layo( grid_title = 'ALV-Grid'
                                    zebra      = abap_true ).
                                    
* ALV-Grid anzeigen
o_alv->set_table_for_first_display( EXPORTING
                                      it_toolbar_excluding = it_excl_toolbuttons
                                      is_layout            = lv_layout
                                    CHANGING
                                      it_fieldcatalog      = it_fcat
                                      it_outtab            = it_tab ).

[ABAP] ALV-Grid: Standard F4-Suchhilfe für Spalten aktivieren

* im LVC-Feldkatalog müssen für die Felder der F4-Spalten folgende Parameter gesetzt werden:
* tabname = 'MARA'.
* ref_table = 'MARA'.
* domname = 'MATNR'.
* f4availabl = abap_true.

DATA: o_alv TYPE REF TO cl_gui_alv_grid.

...

* F4-Hilfe festlegen
DATA(it_f4help) = VALUE lvc_t_f4( ( fieldname = 'MATNR'
                                    register = abap_true
                                    chngeafter = abap_true ) ).

o_alv->register_f4_for_fields( it_f4help ).

[ABAP] GUI-Simple-Tree und SALV-Grid in Split-Container ohne Dynpro anzeigen, Eventhandling

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

DATA: o_salv TYPE REF TO cl_salv_table.
DATA: it_tree_spfli TYPE STANDARD TABLE OF spfli.
DATA: it_salv_spfli TYPE STANDARD TABLE OF spfli.
DATA: it_nodes TYPE ty_it_nodes.

CLASS lcl_events DEFINITION.
  PUBLIC SECTION.
* GUI Simple Tree
    CLASS-METHODS: on_keypress FOR EVENT node_keypress OF cl_gui_simple_tree
      IMPORTING
          node_key
          key
          sender.
    CLASS-METHODS: on_selection_changed FOR EVENT selection_changed OF cl_gui_simple_tree
      IMPORTING
          node_key
          sender.
    CLASS-METHODS: on_expand_no_children FOR EVENT expand_no_children OF cl_gui_simple_tree
      IMPORTING
          node_key
          sender.
* ALV-Events für das SALV-Grid
    CLASS-METHODS: on_toolbar FOR EVENT toolbar OF cl_gui_alv_grid
      IMPORTING
          e_object
          sender.
    CLASS-METHODS: on_user_command FOR EVENT user_command OF cl_gui_alv_grid
      IMPORTING
          e_ucomm
          sender.
ENDCLASS.

CLASS lcl_events IMPLEMENTATION.
* Tastendruck
  METHOD on_keypress.
    MESSAGE |Node: { node_key } Taste: { key }| TYPE 'S'.
  ENDMETHOD.
* Klick auf ein aktives Baumelement
  METHOD on_selection_changed.
* Element in der Nodes-Tabelle lesen
    ASSIGN it_nodes[ node_key = node_key ] TO FIELD-SYMBOL(<fs_node>).

* iTab für SALV-Table neu aufbauen
    CLEAR: it_salv_spfli.

    LOOP AT it_tree_spfli ASSIGNING FIELD-SYMBOL(<fs_line>) WHERE carrid = <fs_node>-text.
      APPEND <fs_line> TO it_salv_spfli.
    ENDLOOP.

* SALV-Table neu anzeigen
    o_salv->refresh( ).
  ENDMETHOD.
* bei Expandierung eines Baumelements ohne Unterelemente
  METHOD on_expand_no_children.
    MESSAGE |Node: { node_key }| TYPE 'S'.
  ENDMETHOD.

* Toolbar-Buttons hinzufügen:
* butn_type   Bezeichung
* 0           Button (normal)
* 1           Menü + Defaultbutton
* 2           Menü
* 3           Separator
* 4           Radiobutton
* 5           Auswahlknopf (Checkbox)
* 6           Menüeintrag
  METHOD on_toolbar.
* Separator hinzufügen
    APPEND VALUE #( butn_type = 3 ) TO e_object->mt_toolbar.
* Edit-Button hinzufügen
    APPEND VALUE #( butn_type = 5 text = 'Daten anzeigen' icon = icon_icon_list function = 'SHOW_DATA' quickinfo = 'Daten anzeigen' disabled = ' ' ) TO e_object->mt_toolbar.
  ENDMETHOD.
* Benutzerkommando (Button-Klick)
  METHOD on_user_command.
    CASE e_ucomm.
      WHEN 'SHOW_DATA'.
        DATA: lv_row TYPE i. " Zeile auf Grid
        DATA: lv_value TYPE char255. " Wert
        DATA: lv_col TYPE i. " Spalte auf Grid
        DATA: lv_row_id TYPE lvc_s_row. " Zeilen-Id
        DATA: lv_col_id TYPE lvc_s_col. " Spalten-Id
        DATA: lv_row_no TYPE lvc_s_roid. " Numerische Zeilen ID

        sender->get_current_cell( IMPORTING
                                    e_row = lv_row
                                    e_value = lv_value
                                    e_col = lv_col
                                    es_row_id = lv_row_id
                                    es_col_id = lv_col_id
                                    es_row_no = lv_row_no ).

        MESSAGE |Zeile: { lv_row }, Spalte: { lv_col }, Wert: { lv_value }, Spaltenname: { lv_col_id-fieldname }| TYPE 'S'.
    ENDCASE.
  ENDMETHOD.

ENDCLASS.

START-OF-SELECTION.

  SELECT * INTO TABLE it_tree_spfli FROM spfli.

* Splitter auf screen0 erzeugen
  DATA(o_split) = NEW cl_gui_splitter_container( parent = cl_gui_container=>screen0
                                                 no_autodef_progid_dynnr = abap_true
                                                 rows = 1
                                                 columns = 2 ).

* Breite in % (linke Spalte für den Tree)
  o_split->set_column_width( id = 1 width = 15 ).

* linken und rechten Splitcontainer holen
  DATA(o_spl_left) = o_split->get_container( row = 1 column = 1 ).
  DATA(o_spl_right) = o_split->get_container( row = 1 column = 2 ).

  TRY.
* Tree-Objekt erzeugen
      DATA(o_tree) = NEW cl_gui_simple_tree( parent = o_spl_left
                                             node_selection_mode = cl_gui_simple_tree=>node_sel_mode_single ).


* Eventtypten müssen gesondert registriert werden
      DATA(it_events) = VALUE ty_it_events( ( eventid = cl_gui_simple_tree=>eventid_node_keypress
                                              appl_event = abap_true )
                                            ( eventid = cl_gui_simple_tree=>eventid_selection_changed
                                              appl_event = abap_true )
                                            ( eventid = cl_gui_simple_tree=>eventid_expand_no_children
                                              appl_event = abap_true ) ).

      o_tree->set_registered_events( events = it_events ).

      o_tree->add_key_stroke( cl_gui_simple_tree=>key_enter ).

* Events registrieren
      SET HANDLER lcl_events=>on_keypress FOR o_tree.
      SET HANDLER lcl_events=>on_selection_changed FOR o_tree.
      SET HANDLER lcl_events=>on_expand_no_children FOR o_tree.

* Root-Node einfügen
      it_nodes = VALUE #( ( node_key  = 'ROOT'           " Node-Bezeichner
                            relatship = cl_gui_simple_tree=>relat_last_child
                            disabled  = abap_true
                            isfolder  = abap_true        " Typ Ordner für Root-Element
                            n_image   = icon_folder      " Icon Ordner
                            exp_image = icon_open_folder " Icon geöffneter Ordner
                            style     = cl_gui_simple_tree=>style_default
                            text      = 'Airlines' ) ).

* Childs an Root-Node anhängen
      LOOP AT it_tree_spfli ASSIGNING FIELD-SYMBOL(<fs_line>).
* bei Änderung der carrid neue carrid als Child anhängen
        AT NEW carrid.
          APPEND VALUE #( node_key  = |NODE{ sy-tabix }| " eindeutiger Node-Bezeichner
                          relatship = cl_gui_simple_tree=>relat_last_child
                          relatkey  = 'ROOT'             " an ROOT-Element anhängen
                          style     = cl_gui_simple_tree=>style_intensified
                          text      = |{ <fs_line>-carrid }| ) TO it_nodes.
        ENDAT.
      ENDLOOP.

* Nodes im Baum einfügen
      o_tree->add_nodes( table_structure_name = 'MTREESNODE' " Typ muss gleich mit Zeilentyp von ty_it_nodes sein
                         node_table           = it_nodes ).

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

* leeres SALV-Grid erzeugen
      cl_salv_table=>factory( EXPORTING
                                r_container    = o_spl_right
                              IMPORTING
                                r_salv_table   = o_salv
                              CHANGING
                                t_table        = it_salv_spfli ).

      o_salv->get_display_settings( )->set_striped_pattern( abap_true ).
      o_salv->get_columns( )->set_optimize( abap_true ).
      o_salv->get_functions( )->set_all( ).
      o_salv->get_selections( )->set_selection_mode( if_salv_c_selection_mode=>row_column ).
      o_salv->display( ).

* Trick: Aus dem Split-Container rechts das Grid-Objekt holen und nach cl_gui_alv_grid casten
      READ TABLE o_spl_right->children INDEX 1 ASSIGNING FIELD-SYMBOL(<child>).
      IF <child> IS ASSIGNED.
        DATA(o_alv_grid) = CAST cl_gui_alv_grid( <child> ).

* Eventhandler registrieren
        SET HANDLER lcl_events=>on_toolbar FOR o_alv_grid.
        SET HANDLER lcl_events=>on_user_command FOR o_alv_grid.
      ENDIF.

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

* leere Toolbar ausblenden
  cl_abap_list_layout=>suppress_toolbar( ).

* cl_gui_container=>screen0 erzwingen
  WRITE space.

[ABAP] SALV-Table: Hilfsklasse zur Ermittlung der Referenz auf ALV-Table (cl_gui_alv_grid) einer SALV-Table (cl_salv_table)

bis SAP-Realease 754: Hilfsklasse lcl_salv_helper abgeleitet von cl_salv_model_base

* bis SAP-Realease 754
* https://zevolving.com/2015/06/salv-table-20-editable-yes-as-per-this-standard-sap-application/

CLASS lcl_salv_helper DEFINITION INHERITING FROM cl_salv_model_base.
  PUBLIC SECTION.

    CLASS-METHODS:
      get_alv_from_salv
        IMPORTING
          io_model       TYPE REF TO cl_salv_model
        RETURNING
          VALUE(ro_grid) TYPE REF TO cl_gui_alv_grid.
ENDCLASS.

CLASS lcl_salv_helper IMPLEMENTATION.
*---------------------------------------------------------------------*
* Wandelt eine Referenz auf cl_salv_table in ein cl_gui_alv_grid um.
* Funktioniert nur, wenn SALV-Table schon mit display( ) angezeigt
* wurde, d.h. schon ein Container dafür erzeugt wurde. Andernfalls ist
* r_adapter INITIAL.
*---------------------------------------------------------------------*
* -> io_model - Referenz auf cl_salv_table (cl_salv_model)
* <- ro_grid  - Referenz auf cl_gui_alv_grid, bei Fehler INITIAL
*---------------------------------------------------------------------*
  METHOD get_alv_from_salv.
  
* wenn Typ 'Table'
    IF io_model->model = if_salv_c_model=>table.
      TRY.
          IF abap_true = cl_wdy_wb_reflection_helper=>is_instance_of( object = io_model->r_controller->r_adapter
                                                                      type_name = 'CL_SALV_GRID_ADAPTER' ).
                                                                      
            DATA(o_grid_adap) = CAST cl_salv_grid_adapter( io_model->r_controller->r_adapter ).

            IF o_grid_adap IS BOUND.
              ro_grid = o_grid_adap->get_grid( ).
            ENDIF.
          ELSEIF abap_true = cl_wdy_wb_reflection_helper=>is_instance_of( object = io_model->r_controller->r_adapter
                                                                          type_name = 'CL_SALV_FULLSCREEN_ADAPTER' ).

            DATA(o_fs_adap) = CAST cl_salv_fullscreen_adapter( io_model->r_controller->r_adapter ).

            IF o_fs_adap IS BOUND.
              ro_grid = o_fs_adap->get_grid( ).
            ENDIF.
          ENDIF.
        CATCH cx_root.
      ENDTRY.
    ENDIF.
  ENDMETHOD.

ENDCLASS.

ab SAP-Release 755: Hilfsklasse lcl_salv_helper mit Nutzung des Interfaces if_salv_table_display_adapter

* ab SAP-Release 755
* SALV-Table: Hilfsklasse zur Ermittlung der Referenz auf ALV-Table (cl_gui_alv_grid) einer SALV-Table (cl_salv_table)
* ab SAP-Release 755 hat die Klasse CL_SALV_FULLSCREEN_ADAPTER keine Funktion get_grid( ) mehr
* somit muss das Coding ab SAP-Release 755 geändert werden
* Quellen:
* https://blogs.sap.com/2022/08/01/editable-cl_salv_table-after-release-756/
* https://tricktresor.de/blog/alv-grid-aus-salv-ermitteln-ab-release-7-55/

CLASS lcl_salv_helper DEFINITION INHERITING FROM cl_salv_model_base FINAL.
  PUBLIC SECTION.

    CLASS-METHODS:
      get_alv_from_salv
        IMPORTING
          io_salv_grid   TYPE REF TO cl_salv_table
        RETURNING
          VALUE(ro_grid) TYPE REF TO cl_gui_alv_grid.
ENDCLASS.

CLASS lcl_salv_helper IMPLEMENTATION.
*---------------------------------------------------------------------*
* Wandelt eine Referenz auf cl_salv_table in ein cl_gui_alv_grid um.
*---------------------------------------------------------------------*
* -> io_model - Referenz auf cl_salv_table (cl_salv_table)
* <- ro_grid  - Referenz auf cl_gui_alv_grid, bei Fehler INITIAL
*---------------------------------------------------------------------*
  METHOD get_alv_from_salv.

    IF io_salv_grid IS BOUND.

      TRY.
          DATA(o_model) = CAST cl_salv_model_base( io_salv_grid->extended_grid_api( ) ).

* Funktioniert nur, wenn SALV-Table schon mit display( ) angezeigt und
* somit schon ein Container dafür erzeugt wurde. Andernfalls ist r_adapter INITIAL.
          IF o_model->r_controller IS BOUND AND o_model->r_controller->r_adapter IS BOUND.

            IF o_model->r_controller->r_adapter IS INSTANCE OF if_salv_table_display_adapter.
              ro_grid = CAST if_salv_table_display_adapter( o_model->r_controller->r_adapter )->get_grid( ).
            ENDIF.

          ENDIF.

        CATCH cx_root.
      ENDTRY.

    ENDIF.

  ENDMETHOD.

ENDCLASS.

Anwendungsbeispiel

* Anwendungs-Beispiel
CLASS lcl_event DEFINITION.
  PUBLIC SECTION.
    CONSTANTS: co_btn_click TYPE string VALUE 'BTN_KLICK'.

    CLASS-METHODS: on_toolbar FOR EVENT toolbar OF cl_gui_alv_grid
      IMPORTING
        e_object
        sender.
    CLASS-METHODS: on_user_command FOR EVENT user_command OF cl_gui_alv_grid
      IMPORTING
        e_ucomm
        sender.
ENDCLASS.

CLASS lcl_event IMPLEMENTATION.
* Toolbar-Buttons hinzufügen
  METHOD on_toolbar.
* Separator hinzufügen
    APPEND VALUE #( butn_type = cntb_btype_sep ) TO e_object->mt_toolbar.
* Edit-Button hinzufügen
    APPEND VALUE #( butn_type = cntb_btype_button
                    text = 'Klick!'
                    icon = icon_change_text
                    function = co_btn_click
                    quickinfo = 'Etwas ausgeben'
                    disabled = abap_false ) TO e_object->mt_toolbar.
  ENDMETHOD.

* User-Command
  METHOD on_user_command.
    CASE e_ucomm.
      WHEN co_btn_click.
        MESSAGE |Klick: { sender->m_guid }| TYPE 'I'.
    ENDCASE.
  ENDMETHOD.
ENDCLASS.

START-OF-SELECTION.

  TRY.
      DATA: o_salv TYPE REF TO cl_salv_table.

* Daten holen
      SELECT FROM t000
        FIELDS *
        INTO TABLE @DATA(it_t000).

      cl_salv_table=>factory( EXPORTING r_container  = cl_gui_container=>default_screen
                              IMPORTING r_salv_table = o_salv
                              CHANGING  t_table      = it_t000 ).

      o_salv->get_functions( )->set_all( ).

      o_salv->display( ).

* Referenz auf ALV-Grid holen
      DATA(o_alv_grid) = lcl_salv_helper=>get_alv_from_salv( o_salv ).

      IF o_alv_grid IS BOUND.
* Eventhandler des ALV-Grids registrieren
        SET HANDLER lcl_event=>on_toolbar FOR o_alv_grid.
        SET HANDLER lcl_event=>on_user_command FOR o_alv_grid.

* Toolbar-Buttons refreshen
        o_alv_grid->refresh_table_display( ).
      ENDIF.
    CATCH cx_root INTO DATA(e_text).
      WRITE: / e_text->get_text( ).
  ENDTRY.

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

* Ausgabe von cl_gui_container=>default_screen erzwingen
  WRITE space.

Links

[ABAP] SALV-Table: Anzeige in einem DockingContainer, Einfügen von Buttons und Eventhandling

Variante 1 (cl_gui_docking_container)

CLASS lcl_event DEFINITION.
  PUBLIC SECTION.
    CLASS-METHODS: handle_toolbar FOR EVENT toolbar OF cl_gui_alv_grid
      IMPORTING e_object
                sender.
    CLASS-METHODS:
      handle_user_command FOR EVENT user_command OF cl_gui_alv_grid
        IMPORTING e_ucomm  " Benutzerkommando
                  sender.  " Sender
ENDCLASS.

CLASS lcl_event IMPLEMENTATION.
  METHOD handle_toolbar.
* Separator hinzufügen
    APPEND VALUE #( butn_type = 3 ) TO e_object->mt_toolbar.
* Print-Button hinzufügen
    APPEND VALUE #( butn_type = 5 text = 'Klick!' icon = icon_change_text function = 'PRINT_DATA' quickinfo = 'Etwas ausgeben' disabled = ' ' ) TO e_object->mt_toolbar.
  ENDMETHOD.

  METHOD handle_user_command.
* TypeCast auf Sender
    DATA: o_grid TYPE REF TO cl_gui_alv_grid.
    o_grid ?= sender.

    CASE e_ucomm.
* Daten speichern
      WHEN 'PRINT_DATA'.
        WRITE: / 'Klick: ', o_grid->m_guid.
    ENDCASE.
  ENDMETHOD.
ENDCLASS.

START-OF-SELECTION.

  DATA: it_data TYPE STANDARD TABLE OF t000.
  DATA: o_salv TYPE REF TO cl_salv_table.

* Daten holen
  SELECT *
    INTO TABLE it_data
    FROM t000.

  DATA(o_dock) = NEW cl_gui_docking_container( no_autodef_progid_dynnr = abap_true
                                               side = cl_gui_docking_container=>dock_at_top
*                                               style = cl_gui_container=>ws_visible + cl_gui_container=>ws_thickframe + cl_gui_container=>ws_child
                                               ratio = 90
                                               caption = 'Datenausgabe'
                                               name = 'CNT1' ).

* Datenanzeige
  TRY.
* Bei Angabe des Containers o_dock bleibt die Abarbeitung nach o_salv->display( ) nicht
* stehen, sondern läuft weiter und die Referenz auf das ALV-Grid kann geholt werden.
* Eine Anzeige des SALV-Grids erfolgt so aber nur, wenn eine Listenausgabe erfolgt, daher das WRITE space.
      cl_salv_table=>factory( EXPORTING
                                r_container    = o_dock
                              IMPORTING
                                r_salv_table   = o_salv
                              CHANGING
                                t_table        = it_data ).

      o_salv->get_functions( )->set_all( ).
      o_salv->display( ).

* Trick: Aus dem Container das Grid-Objekt holen und nach cl_gui_alv_grid casten
      READ TABLE o_dock->children INDEX 1 ASSIGNING FIELD-SYMBOL(<child>).
      DATA(o_alv_grid) = CAST cl_gui_alv_grid( <child> ).

* Eventhandler registrieren
      SET HANDLER lcl_event=>handle_toolbar FOR o_alv_grid.
      SET HANDLER lcl_event=>handle_user_command FOR o_alv_grid.

* Anzeige neu aufbauen
      o_alv_grid->refresh_table_display( ).

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

* leere Toolbar ausblenden
  cl_abap_list_layout=>suppress_toolbar( ).

  WRITE space. " wichtig für Erzwingung der Listenausgabe

Variante 2 (cl_gui_splitter_container)

CLASS lcl_event DEFINITION.
  PUBLIC SECTION.
    CLASS-METHODS:
      handle_toolbar FOR EVENT toolbar OF cl_gui_alv_grid
        IMPORTING e_object
                    sender.
    CLASS-METHODS:
      handle_user_command FOR EVENT user_command OF cl_gui_alv_grid
        IMPORTING e_ucomm  " Benutzerkommando
                    sender.  " Sender
ENDCLASS.

CLASS lcl_event IMPLEMENTATION.
  METHOD handle_toolbar.
* Separator hinzufügen
    APPEND VALUE #( butn_type = 3 ) TO e_object->mt_toolbar.
* Edit-Button hinzufügen
    APPEND VALUE #( butn_type = 5 text = 'Klick!' icon = icon_change_text function = 'PRINT_DATA' quickinfo = 'Etwas ausgeben' disabled = ' ' ) TO e_object->mt_toolbar.
  ENDMETHOD.

  METHOD handle_user_command.
* TypeCast auf Sender
    DATA: o_grid TYPE REF TO cl_gui_alv_grid.
    o_grid ?= sender.

    CASE e_ucomm.
* Daten speichern
      WHEN 'PRINT_DATA'.
        WRITE: / 'Klick: ', o_grid->m_guid.
    ENDCASE.
  ENDMETHOD.

ENDCLASS.

START-OF-SELECTION.

  DATA: it_data TYPE STANDARD TABLE OF t000.
  DATA: o_salv TYPE REF TO cl_salv_table.

* Daten holen
  SELECT *
    INTO TABLE it_data
    FROM t000.

  DATA(o_split) = NEW cl_gui_splitter_container( parent = cl_gui_container=>default_screen
                                                 no_autodef_progid_dynnr = abap_true
                                                 rows = 1
                                                 columns = 2 ). " wenn columns = 1, dann FullScreen

* Referenz auf linken Container holen
  DATA(o_spl_left) = o_split->get_container( row = 1 column = 1 ).

* Datenanzeige
  TRY.
* Bei Angabe des Containers o_spl_left bleibt die Abarbeitung nach o_salv->display( ) nicht
* stehen, sondern läuft weiter und die Referenz auf das ALV-Grid kann geholt werden.
* Eine Anzeige des SALV-Grids erfolgt so aber nur, wenn eine Listenausgabe erfolgt, daher das WRITE space.
      cl_salv_table=>factory( EXPORTING
                                r_container    = o_spl_left
                              IMPORTING
                                r_salv_table   = o_salv
                              CHANGING
                                t_table        = it_data ).

      o_salv->get_functions( )->set_all( ).
      o_salv->display( ).

* Trick: Aus dem Container das Grid-Objekt holen und nach cl_gui_alv_grid casten
      READ TABLE o_spl_left->children INDEX 1 ASSIGNING FIELD-SYMBOL(<child>).
      IF <child> IS ASSIGNED.
        DATA(o_alv_grid) = CAST cl_gui_alv_grid( <child> ).

* Eventhandler registrieren
        SET HANDLER lcl_event=>handle_toolbar FOR o_alv_grid.
        SET HANDLER lcl_event=>handle_user_command FOR o_alv_grid.

* Anzeige neu aufbauen
        o_alv_grid->refresh_table_display( ).
      ENDIF.
    CATCH cx_root INTO DATA(e_text).
      WRITE: / e_text->get_text( ).
  ENDTRY.

* leere Toolbar ausblenden
  cl_abap_list_layout=>suppress_toolbar( ).

  WRITE space. " wichtig für Erzwingung der Listenausgabe 

Variante 3 (cl_gui_container=>screen0)

CLASS lcl_event DEFINITION.
  PUBLIC SECTION.
    CLASS-METHODS: handle_toolbar FOR EVENT toolbar OF cl_gui_alv_grid
      IMPORTING e_object
                sender.
    CLASS-METHODS:
      handle_user_command FOR EVENT user_command OF cl_gui_alv_grid
        IMPORTING e_ucomm  " Benutzerkommando
                  sender.  " Sender
ENDCLASS.

CLASS lcl_event IMPLEMENTATION.
  METHOD handle_toolbar.
* Separator hinzufügen
    APPEND VALUE #( butn_type = 3 ) TO e_object->mt_toolbar.
* Print-Button hinzufügen
    APPEND VALUE #( butn_type = 5 text = 'Klick!' icon = icon_change_text function = 'PRINT_DATA' quickinfo = 'Etwas ausgeben' disabled = ' ' ) TO e_object->mt_toolbar.
  ENDMETHOD.

  METHOD handle_user_command.
* TypeCast auf Sender
    DATA: o_grid TYPE REF TO cl_gui_alv_grid.
    o_grid ?= sender.

    CASE e_ucomm.
* Daten speichern
      WHEN 'PRINT_DATA'.
        WRITE: / 'Klick: ', o_grid->m_guid.
    ENDCASE.
  ENDMETHOD.
ENDCLASS.

START-OF-SELECTION.

  DATA: it_data TYPE STANDARD TABLE OF t000.
  DATA: o_salv TYPE REF TO cl_salv_table.

* Daten holen
  SELECT *
    INTO TABLE it_data
    FROM t000.

* Datenanzeige
  TRY.
* Bei Angabe des Containers cl_gui_container=>screen0 bleibt die Abarbeitung nach o_salv->display( ) nicht
* stehen, sondern läuft weiter und die Referenz auf das ALV-Grid kann geholt werden.
* Eine Anzeige des SALV-Grids erfolgt so aber nur, wenn eine Listenausgabe erfolgt, daher das WRITE space.
      cl_salv_table=>factory( EXPORTING
                                r_container    = cl_gui_container=>screen0
                              IMPORTING
                                r_salv_table   = o_salv
                              CHANGING
                                t_table        = it_data ).

      o_salv->get_functions( )->set_all( ).
      o_salv->display( ).

* Trick: Aus dem Container das Grid-Objekt holen und nach cl_gui_alv_grid casten
      READ TABLE cl_gui_container=>screen0->children INDEX 1 ASSIGNING FIELD-SYMBOL(<child>).
      DATA(o_alv_grid) = CAST cl_gui_alv_grid( <child> ).

* Eventhandler registrieren
      SET HANDLER lcl_event=>handle_toolbar FOR o_alv_grid.
      SET HANDLER lcl_event=>handle_user_command FOR o_alv_grid.

* Anzeige neu aufbauen
      o_alv_grid->refresh_table_display( ).

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

* leere Toolbar ausblenden
  cl_abap_list_layout=>suppress_toolbar( ).

  WRITE space. " wichtig für Erzwingung der Listenausgabe