[ABAP] Mehrere interne Tabellen in eigenem Fullscreen-Fenster (cl_gui_dialogbox_container) anzeigen

CLASS lcl_show_window DEFINITION FINAL.

  PUBLIC SECTION.

    CLASS-METHODS show
      IMPORTING
        !i_title TYPE string
      CHANGING
        !c_itab  TYPE STANDARD TABLE .

    CLASS-METHODS show2
      IMPORTING
        !i_title1 TYPE string
        !i_title2 TYPE string
      CHANGING
        !c_itab1  TYPE STANDARD TABLE
        !c_itab2  TYPE STANDARD TABLE .

  PROTECTED SECTION.

  PRIVATE SECTION.

    CLASS-METHODS on_close
      FOR EVENT close OF cl_gui_dialogbox_container
      IMPORTING
        !sender .
ENDCLASS.

CLASS lcl_show_window IMPLEMENTATION.

  METHOD on_close.
    IF sender IS NOT INITIAL.
      sender->free( ).
    ENDIF.
  ENDMETHOD.

  METHOD show.

    TRY.
* Window-Style hier ohne cl_gui_control=>ws_thickframe vordefinieren, da sonst das Fenster nicht richtig maximized werden kann
        DATA(i_style) = cl_gui_control=>ws_minimizebox + cl_gui_control=>ws_maximizebox + cl_gui_control=>ws_sysmenu.

* Bildschirmauflösung ermitteln
        DATA(lv_metric_factors) = cl_gui_props_consumer=>create_consumer( )->get_metric_factors( ).

* https://download.consolut.com/direct/SAP_PrintDoku/de/BCCIDOCK/BCCIDOCK.PDF
* Top, Left, Width, Height in Pixel
        DATA(o_cnt) = NEW cl_gui_dialogbox_container( no_autodef_progid_dynnr = abap_true
                                                      caption                 = |{ i_title }|
                                                      top                     = 1
                                                      left                    = 1
                                                      width                   = lv_metric_factors-screen-x
                                                      height                  = lv_metric_factors-screen-y
                                                      style                   = i_style
                                                      metric                  = cl_gui_dialogbox_container=>metric_pixel ).

* Dialogbox-Container fullscreen (maximized) setzen
*        o_cnt->set_alignment( cl_gui_control=>align_at_left + cl_gui_control=>align_at_right + cl_gui_control=>align_at_top + cl_gui_control=>align_at_bottom ).

* OnClose-Handler für cl_gui_dialogbox_container
        SET HANDLER on_close FOR o_cnt.

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

        cl_salv_table=>factory( EXPORTING r_container  = o_cnt
                                IMPORTING r_salv_table = o_salv
                                CHANGING  t_table      = c_itab ).

        o_salv->get_functions( )->set_all( abap_true ).
        o_salv->get_columns( )->set_optimize( abap_true ).
        o_salv->get_display_settings( )->set_list_header( |{ i_title }| ).
        o_salv->get_display_settings( )->set_striped_pattern( abap_true ).
        o_salv->get_selections( )->set_selection_mode( if_salv_c_selection_mode=>row_column ).

        o_salv->display( ).

      CATCH cx_root.
    ENDTRY.
  ENDMETHOD.

  METHOD show2.

    TRY.
* Window-Style hier ohne cl_gui_control=>ws_thickframe vordefinieren, da sonst das Fenster nicht richtig maximized werden kann
        DATA(i_style) = cl_gui_control=>ws_minimizebox + cl_gui_control=>ws_maximizebox + cl_gui_control=>ws_sysmenu.

* Bildschirmauflösung ermitteln
        DATA(lv_metric_factors) = cl_gui_props_consumer=>create_consumer( )->get_metric_factors( ).

* https://download.consolut.com/direct/SAP_PrintDoku/de/BCCIDOCK/BCCIDOCK.PDF
* Top, Left, Width, Height in Pixel
        DATA(o_cnt) = NEW cl_gui_dialogbox_container( no_autodef_progid_dynnr = abap_true
                                                      caption                 = |{ i_title1 }, { i_title2 }|
                                                      top                     = 1
                                                      left                    = 1
                                                      width                   = lv_metric_factors-screen-x
                                                      height                  = lv_metric_factors-screen-y
                                                      style                   = i_style
                                                      metric                  = cl_gui_dialogbox_container=>metric_pixel ).

* Dialogbox-Container fullscreen (maximized) setzen
*        o_cnt->set_alignment( cl_gui_control=>align_at_left + cl_gui_control=>align_at_right + cl_gui_control=>align_at_top + cl_gui_control=>align_at_bottom ).

* OnClose-Handler für cl_gui_dialogbox_container
        SET HANDLER on_close FOR o_cnt.

* Referenzen auf GUI-Objekte
* Splitter
        DATA: o_splitter TYPE REF TO cl_gui_splitter_container.

* horizontaler Splitter in cl_gui_dialogbox_container einbetten
        o_splitter = NEW #( parent                  = o_cnt
                            no_autodef_progid_dynnr = abap_true
                            rows                    = 2
                            columns                 = 1 ).

* Splittercontainer auf 50%
        o_splitter->set_row_height( id = 1 height = 50 ).

* Splittercontainer oben/unten holen
        DATA(o_cnt_s1) = o_splitter->get_container( row = 1 column = 1 ).
        DATA(o_cnt_s2) = o_splitter->get_container( row = 2 column = 1 ).

* SALV-Grid 1 in Splittercontainer oben
        DATA: o_salv1 TYPE REF TO cl_salv_table.

        cl_salv_table=>factory( EXPORTING r_container  = o_cnt_s1
                                IMPORTING r_salv_table = o_salv1
                                CHANGING  t_table      = c_itab1 ).

        o_salv1->get_functions( )->set_all( abap_true ).
        o_salv1->get_columns( )->set_optimize( abap_true ).
        o_salv1->get_display_settings( )->set_list_header( |{ i_title1 }| ).
        o_salv1->get_display_settings( )->set_striped_pattern( abap_true ).
        o_salv1->get_selections( )->set_selection_mode( if_salv_c_selection_mode=>row_column ).

        o_salv1->display( ).

* SALV-Grid 2 in Splittercontainer unten
        DATA: o_salv2 TYPE REF TO cl_salv_table.

        cl_salv_table=>factory( EXPORTING r_container  = o_cnt_s2
                                IMPORTING r_salv_table = o_salv2
                                CHANGING  t_table      = c_itab2 ).

        o_salv2->get_functions( )->set_all( abap_true ).
        o_salv2->get_columns( )->set_optimize( abap_true ).
        o_salv2->get_display_settings( )->set_list_header( |{ i_title2 }| ).
        o_salv2->get_display_settings( )->set_striped_pattern( abap_true ).

        o_salv2->get_selections( )->set_selection_mode( if_salv_c_selection_mode=>row_column ).

        o_salv2->display( ).
      CATCH cx_root.
    ENDTRY.
  ENDMETHOD.
ENDCLASS.

START-OF-SELECTION.

* Beispieldaten
  SELECT
    FROM mara
    FIELDS *
    INTO TABLE @DATA(it_mara)
    UP TO 100 ROWS.

  IF sy-subrc = 0.
    SELECT
      FROM marc
      FIELDS *
      INTO TABLE @DATA(it_marc)
      UP TO 100 ROWS.

    IF sy-subrc = 0.
* interne Tabelle im Window anzeigen
      lcl_show_window=>show( EXPORTING i_title = |MARA|
                             CHANGING  c_itab  = it_mara ).

* zwei interne Tabellen in einem Window mit Splitter anzeigen
      lcl_show_window=>show2( EXPORTING i_title1 = |MARA|
                                        i_title2 = |MARC|
                              CHANGING  c_itab1  = it_mara
                                        c_itab2  = it_marc ).
    ENDIF.
  ENDIF.

* cl_gui_container=>default_screen erzwingen
  WRITE: space.

[ABAP] SALV: Eventhandler für Auswahl einer Zeile (Row) bzw. Spalte (Col)

* Eventhandler
CLASS lcl_events DEFINITION.
  PUBLIC SECTION.

* Platzhalter für Referenz auf SALV-Grid
    CLASS-DATA: o_salv TYPE REF TO cl_salv_table.
* Platzhalter für Referenz auf interne Tabelle
    CLASS-DATA: it_t024 TYPE STANDARD TABLE OF t024 WITH DEFAULT KEY.

* Eventhandler-Methode für Change-Select, Verzögerung ~1.5s
    CLASS-METHODS: on_row_select FOR EVENT delayed_changed_sel_callback OF cl_gui_alv_grid
      IMPORTING sender.
ENDCLASS.

CLASS lcl_events IMPLEMENTATION.
* Event behandelt die Auswahl Zeilen/Spalten im Gitter mit 1,5s Verzögerung
  METHOD on_row_select.
    TRY.
* referenz auf ALV-Grid holen
        DATA(o_alv) = CAST cl_gui_alv_grid( sender ).

* selektierte Zeilen, abh. vom if_salv_c_selection_mode
        o_alv->get_selected_rows( IMPORTING et_row_no     = DATA(it_sel_rows)
                                            et_index_rows = DATA(it_sel_rows_idx) ).

* selektierte Spalten, abh. vom if_salv_c_selection_mode
        o_alv->get_selected_columns( IMPORTING et_index_columns = DATA(it_sel_cols_idx) ).

        LOOP AT it_sel_cols_idx ASSIGNING FIELD-SYMBOL(<col>).
        ENDLOOP.

        LOOP AT it_sel_rows_idx ASSIGNING FIELD-SYMBOL(<row>).
        ENDLOOP.

      CATCH cx_root.
    ENDTRY.
  ENDMETHOD.
ENDCLASS.

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

START-OF-SELECTION.

  TRY.
* Beispieldaten (Einkäufergruppen) holen
      SELECT FROM t024
        FIELDS *
        INTO TABLE @lcl_events=>it_t024
        UP TO 10 ROWS.

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

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

* if_salv_c_selection_mode=>single    : es kann eine Zeile im SALV/ALV selektiert werden
* if_salv_c_selection_mode=>row_column: es können mehrere Zeile und Spalten im SALV/ALV selektiert werden
* nach 1,5s wird dann der Event on_delayed_change_select ausgelöst
        lcl_events=>o_salv->get_selections( )->set_selection_mode( if_salv_c_selection_mode=>single ).

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

* ALV-Objektreferenz aus dem SALV-Grid holen, funktioniert erst nach o_salv->display( )
        DATA(o_alv) = lcl_salv_helper=>get_alv_from_salv( lcl_events=>o_salv ).
        IF o_alv IS BOUND.
* Event-Handler des ALV
          SET HANDLER lcl_events=>on_row_select FOR o_alv.
* Event registrieren
          o_alv->register_delayed_event( i_event_id = cl_gui_alv_grid=>mc_evt_delayed_change_select ).
        ENDIF.

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

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

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

[ABAP] SALV-Table – Gruppen für Spaltenvorrat im SALV-Layout

SELECT * FROM sflight INTO TABLE @DATA(it_sflight).

TRY.
* SALV-Table
    DATA: o_salv TYPE REF TO cl_salv_table.

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

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

* Spaltenüberschriften: technischer Name und Beschreibungstexte, Short Text und Medium Text leer lassen für Autosize
    LOOP AT o_salv->get_columns( )->get( ) ASSIGNING FIELD-SYMBOL(<c>).
      DATA(o_col) = <c>-r_column.
      o_col->set_short_text( || ).
      o_col->set_medium_text( || ).
      o_col->set_long_text( |{ o_col->get_columnname( ) } [{ o_col->get_long_text( ) }]| ).
    ENDLOOP.

* Gruppen definieren --> verfügbar im Grid unter Toolbar-Button "Layout ändern ..." --> Spaltenvorrat
    o_salv->get_functional_settings( )->get_specific_groups( )->add_specific_group( id = 'GRP1' text = 'Spaltengruppe 1' ).
    o_salv->get_functional_settings( )->get_specific_groups( )->add_specific_group( id = 'GRP2' text = 'Spaltengruppe 2' ).

* Spalten GRP1 zuordnen
    DATA(o_col_max) = CAST cl_salv_column_list( o_salv->get_columns( )->get_column( 'SEATSMAX' ) ).
    o_col_max->set_specific_group( id = 'GRP1' ).
    DATA(o_col_occ) = CAST cl_salv_column_list( o_salv->get_columns( )->get_column( 'SEATSOCC' ) ).
    o_col_occ->set_specific_group( id = 'GRP1' ).

* Spalten GRP2 zuordnen
    DATA(o_col_max_b) = CAST cl_salv_column_list( o_salv->get_columns( )->get_column( 'SEATSMAX_B' ) ).
    o_col_max_b->set_specific_group( id = 'GRP2' ).
    DATA(o_col_occ_b) = CAST cl_salv_column_list( o_salv->get_columns( )->get_column( 'SEATSOCC_B' ) ).
    o_col_occ_b->set_specific_group( id = 'GRP2' ).
    DATA(o_col_max_f) = CAST cl_salv_column_list( o_salv->get_columns( )->get_column( 'SEATSMAX_F' ) ).
    o_col_max_f->set_specific_group( id = 'GRP2' ).
    DATA(o_col_occ_f) = CAST cl_salv_column_list( o_salv->get_columns( )->get_column( 'SEATSOCC_F' ) ).
    o_col_occ_f->set_specific_group( id = 'GRP2' ).

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

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

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

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

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

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

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

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

      CASE e_salv_function.

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

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

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

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

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

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

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

START-OF-SELECTION.

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

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

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

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

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

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

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

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

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

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

[ABAP] Zwei SALV-Grids in einem Splittercontainer anzeigen

* Daten für SALV-Grid oben
SELECT *
  INTO TABLE @DATA(it_scarr)
  FROM scarr.

* Daten für SALV-Grid unten
SELECT *
  INTO TABLE @DATA(it_sflight)
  FROM sflight.

* Referenzen auf GUI-Objekte
* Splitter
DATA: o_splitter_main TYPE REF TO cl_gui_splitter_container.
* Splitter-Container oben
DATA: o_container_o   TYPE REF TO cl_gui_container.
* Splitter-Container unten
DATA: o_container_u   TYPE REF TO cl_gui_container.

* Splitter auf default_screen erzeugen
o_splitter_main = NEW #( parent                  = cl_gui_container=>default_screen
                         no_autodef_progid_dynnr = abap_true       " wichtig
                         rows                    = 2
                         columns                 = 1 ).

* Höhe oberer Splitter in %
o_splitter_main->set_row_height( id = 1 height = 40 ).

* REF auf oberen und unteren Splitcontainer holen
o_container_o = o_splitter_main->get_container( row = 1 column = 1 ).
o_container_u = o_splitter_main->get_container( row = 2 column = 1 ).

* SALV-Table oben mit Fluggesellschaften
DATA: o_salv_o TYPE REF TO cl_salv_table.

cl_salv_table=>factory( EXPORTING
                          r_container  = o_container_o
                        IMPORTING
                          r_salv_table = o_salv_o
                        CHANGING
                          t_table      = it_scarr ).

* Grundeinstellungen
o_salv_o->get_functions( )->set_all( abap_true ).
o_salv_o->get_columns( )->set_optimize( abap_true ).
o_salv_o->get_display_settings( )->set_list_header( 'Fluggesellschaften' ).
o_salv_o->get_display_settings( )->set_striped_pattern( abap_true ).
o_salv_o->get_selections( )->set_selection_mode( if_salv_c_selection_mode=>row_column ).

* Spaltenüberschriften: technischer Name und Beschreibungstexte
LOOP AT o_salv_o->get_columns( )->get( ) ASSIGNING FIELD-SYMBOL(<so>).
  DATA(o_col_o) = <so>-r_column.
  o_col_o->set_short_text( || ).
  o_col_o->set_medium_text( || ).
  o_col_o->set_long_text( |{ o_col_o->get_columnname( ) }| ).
ENDLOOP.

* SALV-Grid anzeigen
o_salv_o->display( ).

* SALV-Table unten mit Flügen
DATA: o_salv_u TYPE REF TO cl_salv_table.

cl_salv_table=>factory( EXPORTING
                          r_container  = o_container_u
                        IMPORTING
                          r_salv_table = o_salv_u
                        CHANGING
                          t_table      = it_sflight ).

* Grundeinstellungen
o_salv_u->get_functions( )->set_all( abap_true ).
o_salv_u->get_columns( )->set_optimize( abap_true ).
o_salv_u->get_display_settings( )->set_list_header( 'Flüge' ).
o_salv_u->get_display_settings( )->set_striped_pattern( abap_true ).
o_salv_u->get_selections( )->set_selection_mode( if_salv_c_selection_mode=>row_column ).

* Spaltenüberschriften: technischer Name und Beschreibungstexte
LOOP AT o_salv_u->get_columns( )->get( ) ASSIGNING FIELD-SYMBOL(<su>).
  DATA(o_col_u) = <su>-r_column.
  o_col_u->set_short_text( || ).
  o_col_u->set_medium_text( || ).
  o_col_u->set_long_text( |{ o_col_u->get_columnname( ) }| ).
ENDLOOP.

* SALV-Grid anzeigen
o_salv_u->display( ).

* leere Toolbar ausblenden
cl_abap_list_layout=>suppress_toolbar( ).

* Erzwingen von cl_gui_container=>default_screen
WRITE: space.

[ABAP] SALV-Table in der Listausgabe in Custom-Container anzeigen

DATA: o_alv TYPE REF TO cl_salv_table.

START-OF-SELECTION.
  DATA: it_spfli TYPE STANDARD TABLE OF spfli WITH DEFAULT KEY.

  SELECT * FROM spfli INTO CORRESPONDING FIELDS OF TABLE it_spfli.

  WRITE: / 'GUI-Objekt in der Listanzeige'.

  ULINE.

* freier Custom-Container in der Listenansicht
  DATA(o_cnt) = NEW cl_gui_custom_container( container_name = ''
                                             repid          = 'SAPMSSY0'
                                             dynnr          = '0120' ).
* Position des Containers
  o_cnt->set_top( 50 ).
  o_cnt->set_left( 50 ).
  o_cnt->set_width( 1000 ).
  o_cnt->set_height( 200 ).


* SALV-Grid für Anzeige im Container
  TRY.
      cl_salv_table=>factory( EXPORTING
                                r_container  = o_cnt
                              IMPORTING
                                r_salv_table = o_alv
                              CHANGING
                                t_table      = it_spfli ).

      o_alv->display( ).

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

  DO 100 TIMES.
    WRITE: / |{ sy-index } Lorem ipsum.|.
  ENDDO.

[ABAP] SALV-Table: Darstellung (Ausgabeformat) einer Spalte über einen Konvertierungs-Exit anpassen

Beispiel 1: Zeitstempel formatieren (==TSTMP)

DATA: o_alv TYPE REF TO cl_salv_table.

DATA: it_tab TYPE ...

cl_salv_table=>factory( IMPORTING
                          r_salv_table = o_alv
                        CHANGING
                          t_table      = it_tab ).

* Der Inhalt der Spalte 'TIMESTAMP' soll anstelle des zusammengesetzten Standartformates für den p-Datentyp
* eine andere Darstellung, getrennt nach Datum und Uhrzeit, bekommen
* '20180101120101,1234567' -> '01.01.2018 12:01:01'
*
* Dazu wird der vorhandene Konvertierungs-Exit CONVERSION_EXIT_TSTMP_INPUT und CONVERSION_EXIT_TSTMP_OUTPUT
* aufgerufen, indem man das Kürzel '==TSTMP' (mittlere Buchstaben im Bezeichner CONVERSION_EXIT_... ) angibt.
*
* alle vorhandenen Konvertierungs-Exits: Transaktion SE37 -> Funktionsbaustein "CONVERSION_EXIT_*" -> Lupe
* Tabelle: TFDIR
o_alv->get_columns( )->get_column( 'TIMESTAMP' )->set_edit_mask( '==TSTMP' ).

o_alv->display( ).

Beispiel 2: Nachkommastellen abschneiden (==DEC0)

SELECT FROM marc
  FIELDS matnr, werks, eisbe
  INTO TABLE @DATA(it_marc)
  UP TO 100 ROWS.

IF sy-subrc = 0.
  TRY.
*   SALV-Table
      DATA: o_salv TYPE REF TO cl_salv_table.

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

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

*   Spaltenüberschriften: technischer Name und Beschreibungstexte, Short Text und Medium Text leer lassen für Autosize
      LOOP AT o_salv->get_columns( )->get( ) ASSIGNING FIELD-SYMBOL(<c>).
        DATA(o_col) = <c>-r_column.
        o_col->set_short_text( || ).
        o_col->set_medium_text( || ).
        o_col->set_long_text( |{ o_col->get_long_text( ) }| ).
      ENDLOOP.

* Sicherheitsbestand --> Nachkommastellen in der Darstellung abschneiden
      o_salv->get_columns( )->get_column( 'EISBE' )->set_edit_mask( value = '==DEC0' ).

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

Links

[ABAP] SALV-Table: Eigenen Button einfügen und Ereignis abfangen

* http://ajanzen.com/pdf_dokumente/sap_abap/alv/alv_sel_mode_own_funct.pdf

* Eventhandler für neuen Button
CLASS lcl_events DEFINITION.
  PUBLIC SECTION.
* Bezeichner des Buttons
    CONSTANTS: co_btn_xl_export TYPE string VALUE 'BTN_XL_EXPORT'.

    CLASS-METHODS : on_toolbar_click FOR EVENT added_function OF cl_salv_events_table
      IMPORTING
          e_salv_function
          sender.
ENDCLASS.

CLASS lcl_events IMPLEMENTATION.
  METHOD on_toolbar_click.
    CASE e_salv_function.
      WHEN co_btn_xl_export.
        MESSAGE co_btn_xl_export TYPE 'S'.
    ENDCASE.
  ENDMETHOD.
ENDCLASS.

START-OF-SELECTION.

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

  DATA: o_alv TYPE REF TO cl_salv_table.
  DATA: it_tab TYPE ...

  cl_salv_table=>factory( EXPORTING
                            r_container = cl_gui_container=>default_screen
                          IMPORTING
                            r_salv_table = o_alv
                          CHANGING
                            t_table = it_tab ).

* Standardbuttons der SALV-Table ausblenden
  o_alv->get_functions( )->set_all( abap_false ).

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

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

* SALV anzeigen
  o_alv->display( ).

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

[ABAP] Selektionsbild mit HTML-Elementen, Dateneingabe, SALV-Grid, CSS, Eventhandling

**********************************************************************
*
* Datentypen, Variablen, Konstanten
*
**********************************************************************
TYPES: ty_it_events TYPE STANDARD TABLE OF cntl_simple_event WITH DEFAULT KEY.

CONSTANTS: co_carrid TYPE string VALUE 'carrid'.
CONSTANTS: co_airpto TYPE string VALUE 'airpto'.

DATA: o_splitter_main TYPE REF TO cl_gui_splitter_container.
DATA: o_container_l   TYPE REF TO cl_gui_container.
DATA: o_container_r   TYPE REF TO cl_gui_container.
DATA: o_html TYPE REF TO cl_gui_html_viewer.
DATA: o_salv TYPE REF TO cl_salv_table.

DATA: it_spfli TYPE STANDARD TABLE OF spfli WITH DEFAULT KEY.
DATA: it_salv_spfli TYPE STANDARD TABLE OF spfli WITH DEFAULT KEY.
DATA: it_sairport TYPE STANDARD TABLE OF sairport WITH DEFAULT KEY.

DATA: it_html TYPE html_table.
**********************************************************************
*
* Eventhandler
*
**********************************************************************
CLASS lcl_html_events DEFINITION.
  PUBLIC SECTION.
    CLASS-METHODS:
      on_sapevent FOR EVENT sapevent OF cl_gui_html_viewer
        IMPORTING
            action
            frame
            getdata
            postdata
            query_table
            sender.
ENDCLASS.

CLASS lcl_html_events IMPLEMENTATION.
* Link- oder Button-Klick
  METHOD on_sapevent.
    IF o_salv IS BOUND.
      TRY.
* Element in der Nodes-Tabelle lesen
          ASSIGN query_table[ name = co_carrid ] TO FIELD-SYMBOL(<carrid>).
          ASSIGN query_table[ name = co_airpto ] TO FIELD-SYMBOL(<airpto>).

          IF <carrid> IS ASSIGNED AND <airpto> IS ASSIGNED.
* iTab für SALV-Table neu aufbauen, abhängig von der Eingabe in den Formularfeldern
            it_salv_spfli = VALUE #( FOR <f> IN it_spfli WHERE ( ( carrid = <carrid>-value ) AND ( airpto = <airpto>-value ) )
                                     ( <f> )
                                   ).

          ENDIF.

* SALV-Table neu anzeigen
          o_salv->refresh( ).
        CATCH cx_root INTO DATA(e_txt).
          MESSAGE e_txt->get_text( ) TYPE 'S'.
      ENDTRY.
    ENDIF.
  ENDMETHOD.
ENDCLASS.
**********************************************************************
*
* SELECTION-SCREEN
*
**********************************************************************
* leeres Selektionsbild als Dummy für die Container-Objekte (o_splitter_main ...)
SELECTION-SCREEN BEGIN OF SCREEN 2000.
SELECTION-SCREEN END OF SCREEN 2000.
**********************************************************************
*
* INITIALIZATION
*
**********************************************************************
INITIALIZATION.
* Daten holen
  SELECT * INTO TABLE it_spfli FROM spfli.
  SELECT * INTO TABLE it_sairport FROM sairport.

* HTML-Code mit Buttons und Forms
  it_html = VALUE #(
                     ( |<html>| )
                     ( |  <head>| )
                     ( |    <meta http-equiv="content-type" content="text/html; charset=utf-8">| )
                     ( |    <script type="text/javascript">| )
                     ( |      function onKeyDown(f)| )
                     ( |      \{ if(event.keyCode == 13)| )
                     ( |         \{ document[f.name].submit();| )
                     ( |         \}| )
                     ( |      \}| )
                     ( |    </script>| )
                     ( |    <style type="text/css">| )
                     ( |       body \{| )
                     ( |         font-family: Courier New;| )
                     ( |         font-size: 13px;| )
                     ( |         font-style: normal;| )
                     ( |         font-variant: normal;| )
                     ( |         font-weight: 400;| )
                     ( |         line-height: 13px;| )
                     ( |       \}| )
                     ( |       form \{| )
                     ( |         background: lightblue;| )
                     ( |       \}| )
                     ( |       label \{| )
                     ( |         text-align: right;| )
                     ( |         line-height: 1.5;| )
                     ( |         float: left;| )
                     ( |         width: 40%;| )
                     ( |       \}| )
                     ( |       input \{| )
                     ( |         margin: 0 0 1em .2em;| )
                     ( |         padding: .2em .5em;| )
                     ( |         background-color: #fffbf0;| )
                     ( |         border: 1px solid #e7c157;| )
                     ( |         float: left;| )
                     ( |         width: 40%;| )
                     ( |         font-family: Courier New;| )
                     ( |         font-size: 13px;| )
                     ( |         font-style: normal;| )
                     ( |         font-variant: normal;| )
                     ( |         font-weight: 400;| )
                     ( |         line-height: 13px;| )
                     ( |       \}| )
                     ( |       select \{| )
                     ( |         margin: 0 0 1em .2em;| )
                     ( |         padding: .2em .5em;| )
                     ( |         background-color: #fffbf0;| )
                     ( |         border: 1px solid #e7c157;| )
                     ( |         float: left;| )
                     ( |         width: 40%;| )
                     ( |         font-family: Courier New;| )
                     ( |         font-size: 13px;| )
                     ( |         font-style: normal;| )
                     ( |         font-variant: normal;| )
                     ( |         font-weight: 400;| )
                     ( |         line-height: 13px;| )
                     ( |       \}| )
                     ( |       button \{| )
                     ( |         margin-top: 1.5em;| )
                     ( |         float: right;| )
                     ( |       \}| )
                     ( |      </style>| )
                     ( |  </head>| )
                     ( |  <body>| )
                     ( |    <form name="INPUT" accept-charset="utf-8" method="post" action="SAPEVENT:INPUT_FIELDS">| )
                     ( |      <br>| )
                     ( |      <label for="{ co_carrid }">Fluggesellschaft:</label>| )
                     ( |      <input type="text" name="{ co_carrid }" value="LH" onKeyDown="onKeyDown(this.form);">| )
                     ( |      <br>| )
                     ( |      <label for="{ co_airpto }">Zielflughafen:</label>| )
                     ( |      <select name="{ co_airpto }" value="JFK">| )
                   ).

  LOOP AT it_sairport ASSIGNING FIELD-SYMBOL(<a>).
    IF <a>-id = 'JFK'.
      APPEND |        <option selected>{ <a>-id }</option>| TO it_html.
    ELSE.
      APPEND |        <option>{ <a>-id }</option>| TO it_html.
    ENDIF.
  ENDLOOP.

  it_html = VALUE #( BASE it_html
                     ( |      </select>| )
                     ( |      <br>| )
                     ( |      <button type="submit" title="Anzeigen">Anzeigen</button>| )
                     ( |      <br>| )
                     ( |      <br>| )
                     ( |      <br>| )
                     ( |      <br>| )
                     ( |    </form>| )
                     ( |  </body>| )
                     ( |</html>| )
                   ).

**********************************************************************
*
* AT SELECTION-SCREEN OUTPUT
*
**********************************************************************
AT SELECTION-SCREEN OUTPUT.
* Doppelte Objekterzeugung unterbinden
  IF NOT o_splitter_main IS BOUND.
* Splitter auf default_screen (SELECTION-SCREEN 2000) erzeugen
    o_splitter_main = NEW #( parent  = cl_gui_container=>default_screen
                             rows    = 1
                             columns = 2 ).

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

* linken und rechten Splitcontainer holen
    o_container_l = o_splitter_main->get_container( row = 1 column = 1 ).
    o_container_r = o_splitter_main->get_container( row = 1 column = 2 ).

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

* Eventtypten müssen gesondert registriert werden
    DATA(it_events) = VALUE ty_it_events( ( 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_html_events=>on_sapevent FOR o_html.

* URL zu HTML holen
    DATA: lv_url TYPE skwf_url.

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

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

    it_salv_spfli = it_spfli.

* SALV-Table für Anzeige der Daten
    cl_salv_table=>factory( EXPORTING
                              r_container    = o_container_r
                            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( ).
  ENDIF.
**********************************************************************
*
* AT SELECTION-SCREEN
*
**********************************************************************
AT SELECTION-SCREEN.
* wenn "Ausführen" (F8) geklickt wurde
  IF sy-ucomm = 'CRET'.
* Selektionbild 2000 wieder anzeigen
    CALL SELECTION-SCREEN 2000.
  ENDIF.
**********************************************************************
*
* START-OF-SELECTION
*
**********************************************************************
START-OF-SELECTION.
* leeres Selektionbild 2000 anzeigen
  CALL SELECTION-SCREEN 2000.