[ABAP] SALV-Table: Nullwerte verbergen

* Variante 1: Für eine Spalte des Gitters 
DATA(o_col) = CAST cl_salv_column( o_alv->get_columns( )->get_column( 'MATNR' ) ).
o_col->set_zero( abap_false ).

* Variante 2: Für alle Spalten des Gitters: Nullwerte anzeigen/verstecken
LOOP AT o_alv->get_columns( )->get( ) ASSIGNING FIELD-SYMBOL(<c>).
  <c>-r_column->set_zero( abap_false ).
ENDLOOP.

[ABAP] SALV IDA: Funktionsbutton einfügen

DATA: o_alv TYPE REF TO if_salv_gui_table_ida.

CLASS lcl_events DEFINITION.
  PUBLIC SECTION.
* Konstante für Button-Event
    CONSTANTS: co_btn_showdetail type UI_FUNC VALUE 'SHOW_DETAIL'.

    CLASS-METHODS: on_toolbar_function_selected FOR EVENT function_selected OF if_salv_gui_toolbar_ida
      IMPORTING
          ev_fcode
          sender.
ENDCLASS.

CLASS lcl_events IMPLEMENTATION.

  METHOD on_toolbar_function_selected.
    DATA: lv_row TYPE sflight.

    CASE ev_fcode.
* wenn Button-Funktion
      WHEN co_btn_showdetail.

        IF abap_true = o_alv->selection( )->is_row_selected( ).
* ganzen Datensatz holen
          o_alv->selection( )->get_selected_row( EXPORTING
                                                   iv_request_type = if_salv_gui_selection_ida=>cs_request_type-all_fields
                                                 IMPORTING
                                                   es_row = lv_row ).
* Datensatz anzeigen
          cl_salv_ida_show_data_row=>display( iv_text = 'Flug-Details'
                                              is_data = lv_row ).
        ENDIF.
    ENDCASE.
  ENDMETHOD.

ENDCLASS.

START-OF-SELECTION.

  o_alv = cl_salv_gui_table_ida=>create( iv_table_name = 'SFLIGHT' ).

* Single-Selection
  o_alv->selection( )->set_selection_mode( if_salv_gui_selection_ida=>cs_selection_mode-single ).

* Toolbar button einfügen
  o_alv->toolbar( )->add_button( EXPORTING
                                   iv_fcode                     = lcl_events=>co_btn_showdetail
                                   iv_icon                      = icon_flight
                                   iv_text                      = 'Details'
                                   iv_quickinfo                 = 'Flug-Details'
                                   iv_before_standard_functions = abap_true ).
* Separator
  o_alv->toolbar( )->add_separator( EXPORTING
                                      iv_before_standard_functions = abap_true ).

* Event-handler
  SET HANDLER lcl_events=>on_toolbar_function_selected FOR o_alv->toolbar( ).

* Tabelle anzeigen
  o_alv->fullscreen( )->display( ).

[ABAP] SALV IDA: Klick-Events (Link, Button, Doppelklick) abfangen

CLASS lcl_events DEFINITION.
  PUBLIC SECTION.
    CLASS-METHODS: on_cell_click FOR EVENT cell_action OF if_salv_gui_field_display_opt
      IMPORTING
          ev_field_name
          eo_row_data
          sender.

    CLASS-METHODS: on_double_click FOR EVENT double_click OF if_salv_gui_table_display_opt
      IMPORTING
          ev_field_name
          eo_row_data
          sender.
ENDCLASS.

CLASS lcl_events IMPLEMENTATION.

  METHOD on_cell_click.
    DATA: lv_row TYPE sflight.

    eo_row_data->get_row_data( EXPORTING
                                 iv_request_type = if_salv_gui_selection_ida=>cs_request_type-all_fields
                               IMPORTING
                                 es_row = lv_row ).

    cl_salv_ida_show_data_row=>display( iv_text = |Datenfeld: { ev_field_name }|
                                        is_data = lv_row ).
  ENDMETHOD.

  METHOD on_double_click.
    DATA: lv_row TYPE sflight.

* Daten der geklickten Zeile holen
    eo_row_data->get_row_data( EXPORTING
                                 iv_request_type = if_salv_gui_selection_ida=>cs_request_type-all_fields
                               IMPORTING
                                 es_row =  lv_row ).

* Daten anzeigen
    cl_salv_ida_show_data_row=>display( iv_text = |Datenfeld: { ev_field_name }|
                                        is_data = lv_row ).
  ENDMETHOD.

ENDCLASS.

START-OF-SELECTION.

  DATA(o_alv) = cl_salv_gui_table_ida=>create( iv_table_name = 'SFLIGHT' ).

* Single-Selection
  o_alv->selection( )->set_selection_mode( if_salv_gui_selection_ida=>cs_selection_mode-single ).

* Zellen der Spalte 'CONNID' sind als Link klickbar
  o_alv->field_catalog( )->display_options( )->display_as_link_to_action( iv_field_name = 'CONNID' ).
  SET HANDLER lcl_events=>on_cell_click FOR o_alv->field_catalog( )->display_options( ).

* Zellen der Spalte 'CARRID' sind als Button klickbar
  o_alv->field_catalog( )->display_options( )->display_as_button( iv_field_name = 'CARRID' ).
  SET HANDLER lcl_events=>on_cell_click FOR o_alv->field_catalog( )->display_options( ).

* Double-Click für alle Zellen
  o_alv->display_options( )->enable_double_click( ).
  SET HANDLER lcl_events=>on_double_click FOR o_alv->display_options( ).

* Tabelle anzeigen
  o_alv->fullscreen( )->display( ).

[ABAP] SALV IDA: Icons und Buttons einfügen, Klick-Events abfangen

CLASS lcl_event_handler DEFINITION.
  PUBLIC SECTION.
    INTERFACES: if_salv_ida_calc_field_handler.

    METHODS: on_cell_action FOR EVENT cell_action OF if_salv_gui_field_display_opt
      IMPORTING
          ev_field_name
          eo_row_data
          sender.

  PRIVATE SECTION.
    TYPES:
      BEGIN OF ty_calc_field,
        icon   TYPE char4,
        button TYPE lvc_value,
      END OF ty_calc_field.

    TYPES: BEGIN OF ty_line.
            INCLUDE TYPE sflight.
            INCLUDE TYPE ty_calc_field.
    TYPES: END OF ty_line.
ENDCLASS.

CLASS lcl_event_handler IMPLEMENTATION.

  METHOD on_cell_action.
    DATA: lv_row TYPE ty_line.

    eo_row_data->get_row_data( EXPORTING
                                 iv_request_type = if_salv_gui_selection_ida=>cs_request_type-all_fields
                               IMPORTING
                                 es_row = lv_row ).

    cl_salv_ida_show_data_row=>display( iv_text = |Datenfeld: { ev_field_name }|
                                        is_data = lv_row ).
  ENDMETHOD.

  METHOD if_salv_ida_calc_field_handler~get_calc_field_structure.
* Struktur-Deklaration für zus. Felder ICON und BUTTON zurückgeben
    ro_calc_field_structure = CAST cl_abap_structdescr( cl_abap_structdescr=>describe_by_name( 'TY_CALC_FIELD' ) ).
  ENDMETHOD.

  METHOD if_salv_ida_calc_field_handler~get_requested_fields.
  ENDMETHOD.

  METHOD if_salv_ida_calc_field_handler~calculate_line.

* Daten akt. Zeile holen
    DATA(lv_sflight) = CONV sflight( is_data_base_line ).

* Freie Sitze ausrechnen
    DATA(lv_cnt_free_seats) = lv_sflight-seatsmax - lv_sflight-seatsocc.

* Calculated Fields bestimmen
    es_calculated_fields = COND ty_calc_field( WHEN lv_cnt_free_seats = 0  THEN VALUE #( icon = icon_red_light    button = icon_delete )
                                               WHEN lv_cnt_free_seats > 10 THEN VALUE #( icon = icon_green_light  button = icon_okay )
                                                                           ELSE VALUE #( icon = icon_yellow_light button = space )
                                             ).

  ENDMETHOD.

  METHOD if_salv_ida_calc_field_handler~start_page.
  ENDMETHOD.

  METHOD if_salv_ida_calc_field_handler~end_page.
  ENDMETHOD.

ENDCLASS.

START-OF-SELECTION.

  DATA(o_handler) = NEW lcl_event_handler( ).

  DATA(o_alv) = cl_salv_gui_table_ida=>create( iv_table_name         = 'SFLIGHT'
                                               io_calc_field_handler = o_handler ). " Referenz für Fieldhandler

* Single-Selection
  o_alv->selection( )->set_selection_mode( if_salv_gui_selection_ida=>cs_selection_mode-single ).

* Tooltips für Icons
  DATA(it_icon_tooltip) = VALUE if_salv_gui_types_ida=>yts_icon_tooltip( ( icon    = icon_yellow_light
                                                                           tooltip = 'Weniger als 10 Sitze.' )
                                                                         ( icon    = icon_green_light
                                                                           tooltip = 'Ausreichend Sitze.' )
                                                                         ( icon    = icon_red_light
                                                                           tooltip = 'Keine Sitze mehr frei.' ) ).

* Tooltips setzen: Feldname 'ICON' muss identisch mit ty_calc_field-icon sein!
  o_alv->field_catalog( )->display_options( )->set_tooltip_for_icons( iv_field_name = 'ICON'
                                                                      its_tooltips  = it_icon_tooltip ).

* Überschrift für Spalte 'ICON': Feldname 'ICON' muss identisch mit ty_calc_field-icon sein!
  o_alv->field_catalog( )->set_field_header_texts( iv_field_name  = 'ICON'
                                                   iv_header_text = 'Status' ).

* Zellen der Spalte 'ICON' sind klickbar: Feldname 'ICON' muss identisch mit ty_calc_field-icon sein!
  o_alv->field_catalog( )->display_options( )->display_as_link_to_action( iv_field_name = 'ICON' ).


* Tooltips für Buttons: Feldname 'BUTTON' muss identisch mit ty_calc_field-icon sein!
  o_alv->field_catalog( )->display_options( )->set_tooltip_for_icons( iv_field_name           = 'BUTTON'
                                                                      iv_use_standard_tooltip = abap_true ).

* Wenn leere Buttonwerte in der Funktion if_salv_ida_calc_field_handler~calculate_line erzeugt werden (INITIAL),
* dann keine Buttons anzeigen
* Feldname 'BUTTON' muss identisch mit ty_calc_field-button sein!
  o_alv->field_catalog( )->display_options( )->display_as_button( iv_field_name               = 'BUTTON'
                                                                  iv_hide_if_value_is_initial = abap_true ).

* Überschrift für Spalte 'BUTTON': Feldname 'BUTTON' muss identisch mit ty_calc_field-button sein!
  o_alv->field_catalog( )->set_field_header_texts( iv_field_name  = 'BUTTON'
                                                   iv_header_text = 'Aktion' ).

* Click-Handler für Icons und Buttons aktivieren
  SET HANDLER o_handler->on_cell_action FOR o_alv->field_catalog( )->display_options( ).

* Tabelle anzeigen
  o_alv->fullscreen( )->display( ).

[ABAP] ALV-Grid auf dem Selektionsbildschirm anzeigen, Klick-Events abfangen, Selektions-Parameter setzen

DATA: o_dock TYPE REF TO cl_gui_docking_container.
DATA: o_alv TYPE REF TO cl_gui_alv_grid.
DATA: it_t001 TYPE STANDARD TABLE OF t001.
DATA: lv_temp TYPE string.

SELECTION-SCREEN BEGIN OF BLOCK var WITH FRAME TITLE title1.
PARAMETERS: p_param1 TYPE string.
SELECTION-SCREEN END OF BLOCK var.

CLASS lcl_events DEFINITION.
  PUBLIC SECTION.
    METHODS: on_single_click FOR EVENT hotspot_click OF cl_gui_alv_grid
      IMPORTING
        e_row_id  " obsolet, stattdessen es_row_no benutzen
        es_row_no
        e_column_id.
    METHODS: on_double_click FOR EVENT double_click OF cl_gui_alv_grid
      IMPORTING
        e_row e_column.
ENDCLASS.

CLASS lcl_events IMPLEMENTATION.
* Doppel-Klick für Hotspot-Felder
  METHOD on_double_click.
    IF e_row > 0.
      lv_temp = it_t001[ e_row ]-butxt.
    ENDIF.
  ENDMETHOD.

* Single-Klick für Hotspot-Felder
  METHOD on_single_click.
    IF es_row_no-row_id > 0.
      lv_temp = it_t001[ es_row_no-row_id ]-butxt.
    ENDIF.
  ENDMETHOD.
ENDCLASS.

INITIALIZATION.

  title1 = 'Selektion'.

* Daten holen
  SELECT * FROM t001 INTO TABLE it_t001.

* Docking-Container erzeugen
  o_dock = NEW #( side = cl_gui_docking_container=>dock_at_left
                  ratio = 20 ).

* ALV-Grid erzeugen
  o_alv = NEW #( i_parent = o_dock
                 i_appl_events = abap_true ).

* Eventhandler setzen
  DATA(o_events) = NEW lcl_events( ).
  SET HANDLER o_events->on_double_click FOR o_alv.
  SET HANDLER o_events->on_single_click FOR o_alv.

* Layout anpassen
  DATA(lv_layout) = VALUE lvc_s_layo( grid_title = 'Auswahl mit Doppelklick:'
                                      no_toolbar = abap_false
                                      smalltitle = abap_true
                                      zebra      = abap_true ).

* ALV-Grid initialisieren
  o_alv->set_table_for_first_display( EXPORTING
                                        i_structure_name = 'T001'
                                        i_save           = space
                                        is_layout        = lv_layout
                                      CHANGING
                                        it_outtab        = it_t001 ).

* Feldkatalog holen
  DATA: it_fcat TYPE lvc_t_fcat.
    
  o_alv->get_frontend_fieldcatalog( IMPORTING
                                      et_fieldcatalog = it_fcat ).

* Hotspot für die Spalte 'BUTXT' aktivieren, damit Event handle_single_click abgefangen werden kann
  LOOP AT it_fcat ASSIGNING FIELD-SYMBOL(<fcat>).
    CASE <fcat>-fieldname.
      WHEN 'BUTXT'.
        <fcat>-hotspot = abap_true.
    ENDCASE.
  ENDLOOP.

* Feldkatalog speichern
  o_alv->set_frontend_fieldcatalog( it_fieldcatalog = it_fcat ).

* ALV-Grid anzeigen
  o_alv->refresh_table_display( ).

AT SELECTION-SCREEN OUTPUT.
* Selektion an Parameter geben
  p_param1 = lv_temp.

START-OF-SELECTION.
  WRITE: / 'Gewählter Parameter: ', p_param1.

[ABAP] Ein SALV-Table IDA und ein GUI-Picture in einem Dockingcontainer direkt auf dem Selektionsbildschirm anzeigen

DATA: o_cnt_bottom TYPE REF TO cl_gui_docking_container.
DATA: o_cnt_right TYPE REF TO cl_gui_docking_container.
DATA: o_alv_bottom TYPE REF TO if_salv_gui_table_ida.
DATA: o_pic TYPE REF TO cl_gui_picture.
DATA: o_collector_bottom TYPE REF TO cl_salv_range_tab_collector.
DATA: lv_mtart TYPE mara-mtart.

SELECTION-SCREEN BEGIN OF BLOCK b1 WITH FRAME TITLE title2.
SELECT-OPTIONS: s_mtart FOR lv_mtart.
SELECTION-SCREEN END OF BLOCK b1.

AT SELECTION-SCREEN OUTPUT.

* Verhindern, dass der Container mehrfach erzeugt wird, wenn der Focus aus
* best. Oberflächenelementen zurück kommt.

* Container unten erzeugen
  IF NOT o_cnt_bottom IS BOUND.
    o_cnt_bottom = NEW #( repid = sy-repid
                          dynnr = sy-dynnr
                          side  = cl_gui_docking_container=>dock_at_bottom " unterer Bildschirmrand
                          extension = 300 ).                               " 300 hoch, damit die Selektionskriterien nicht überdeckt werden
* Container rechts erzeugen

    o_cnt_right = NEW #( repid = sy-repid
                         dynnr = sy-dynnr
                         side  = cl_gui_docking_container=>dock_at_right  " rechter Bildschirmrand
                         extension = 800 ).                               " 800 breit, damit die Selektionskriterien nicht überdeckt werden

* IDA-Grid unten erzeugen
    o_alv_bottom = cl_salv_gui_table_ida=>create( iv_table_name    = 'MARA'
                                                  io_gui_container = o_cnt_bottom ).
    o_alv_bottom->display_options( )->set_title( 'MARA' ).

* Picture rechts erzeugen
    o_pic = NEW #( parent = o_cnt_right ).
    o_pic->set_display_mode( display_mode = cl_gui_picture=>display_mode_normal_center ).
    o_pic->load_picture_from_sap_icons( icon  = icon_delete ).

* Suchkriterien unten setzen
    o_collector_bottom = NEW #( ).
    o_collector_bottom->add_ranges_for_name( iv_name = 'MTART' it_ranges = s_mtart[] ).
    o_collector_bottom->get_collected_ranges( IMPORTING et_named_ranges = DATA(it_name_range_pairs_bottom) ).

    o_alv_bottom->set_select_options( it_ranges = it_name_range_pairs_bottom ).
  ENDIF.

[ABAP] Zwei SALV-Table IDA in einem Dockingcontainer direkt auf dem Selektionsbildschirm anzeigen

DATA: o_cnt_bottom TYPE REF TO cl_gui_docking_container.
DATA: o_cnt_right TYPE REF TO cl_gui_docking_container.
DATA: o_alv_bottom TYPE REF TO if_salv_gui_table_ida.
DATA: o_alv_right TYPE REF TO if_salv_gui_table_ida.
DATA: o_collector_bottom TYPE REF TO cl_salv_range_tab_collector.
DATA: o_collector_right TYPE REF TO cl_salv_range_tab_collector.

DATA: lv_arbgb TYPE t100-arbgb.
DATA: lv_msg TYPE t100-msgnr.
DATA: lv_text TYPE t100-text.
DATA: lv_mtart TYPE mara-mtart.

* Selektionskriterien für T100
SELECTION-SCREEN BEGIN OF BLOCK b1 WITH FRAME TITLE title1.
SELECT-OPTIONS: s_langu FOR sy-langu.
SELECT-OPTIONS: s_arbgb FOR lv_arbgb.
SELECT-OPTIONS: s_msg FOR lv_msg.
SELECT-OPTIONS: s_text FOR lv_text.
SELECTION-SCREEN END OF BLOCK b1.

* Selektionskriterien für MARA
SELECTION-SCREEN BEGIN OF BLOCK b2 WITH FRAME TITLE title2.
SELECT-OPTIONS: s_mtart FOR lv_mtart.
SELECTION-SCREEN END OF BLOCK b2.

AT SELECTION-SCREEN OUTPUT.

* Verhindern, dass der Container mehrfach erzeugt wird, wenn der Focus aus
* best. Oberflächenelementen zurück kommt.
  IF NOT o_cnt_bottom IS BOUND.
* Container unten erzeugen
    o_cnt_bottom = NEW #( repid = sy-repid
                          dynnr = sy-dynnr
                          side = cl_gui_docking_container=>dock_at_bottom  " unterer Bildschirmrand
                          extension = 300 ).                               " 300 hoch, damit die Selektionskriterien nicht überdeckt werden

* Container rechts erzeugen
    o_cnt_right = NEW #( repid = sy-repid
                         dynnr = sy-dynnr
                         side = cl_gui_docking_container=>dock_at_right  " rechter Bildschirmrand
                         extension = 800 ).                              " 800 breit, damit die Selektionskriterien nicht überdeckt werden


* IDA-Grid unten erzeugen
    o_alv_bottom = cl_salv_gui_table_ida=>create( iv_table_name    = 'MARA'
                                                  io_gui_container = o_cnt_bottom ).
    o_alv_bottom->display_options( )->set_title( 'MARA' ).

* IDA-Grid rechts erzeugen
    o_alv_right = cl_salv_gui_table_ida=>create( iv_table_name    = 'T100'
                                                 io_gui_container = o_cnt_right ).
    o_alv_right->display_options( )->set_title( 'T100' ).

* Suchkriterien unten setzen
    o_collector_bottom = NEW #( ).
    o_collector_bottom->add_ranges_for_name( iv_name = 'MTART' it_ranges = s_mtart[] ).
    o_collector_bottom->get_collected_ranges( IMPORTING et_named_ranges = DATA(it_name_range_pairs_bottom) ).

    o_alv_bottom->set_select_options( it_ranges = it_name_range_pairs_bottom ).

* Suchkriterien rechts setzen
    o_collector_right = NEW #( ).
    o_collector_right->add_ranges_for_name( iv_name = 'SPRSL' it_ranges = s_langu[] ).
    o_collector_right->add_ranges_for_name( iv_name = 'ARBGB' it_ranges = s_arbgb[] ).
    o_collector_right->add_ranges_for_name( iv_name = 'MSGNR' it_ranges = s_msg[] ).
    o_collector_right->add_ranges_for_name( iv_name = 'TEXT' it_ranges = s_text[] ).
    o_collector_right->get_collected_ranges( IMPORTING et_named_ranges = DATA(it_name_range_pairs_right) ).

    o_alv_right->set_select_options( it_ranges = it_name_range_pairs_right ).
  ENDIF.