[ABAP] SALV-Tree: Beispiel für Verwendung von cl_salv_tree

* Demoprogramme
*
* SALV_DEMO_TREE_DATA_UPDATE
* SALV_DEMO_TREE_EVENTS
* SALV_DEMO_TREE_FUNCTIONS
* SALV_DEMO_TREE_METADATA
* SALV_DEMO_TREE_SELECTIONS
* SALV_DEMO_TREE_SETTINGS
* SALV_DEMO_TREE_SIMPLE

TYPES: ty_it_spfli TYPE STANDARD TABLE OF spfli WITH DEFAULT KEY.

DATA: o_tree TYPE REF TO cl_salv_tree.
DATA: it_spfli TYPE ty_it_spfli.
DATA: it_spfli_empty TYPE ty_it_spfli.

* Eventhandlerklasse
CLASS lcl_events DEFINITION.
  PUBLIC SECTION.

    CLASS-METHODS:
      on_button_click FOR EVENT link_click OF cl_salv_events_tree
        IMPORTING
            columnname
            node_key
            sender.
    CLASS-METHODS:
      on_user_command FOR EVENT added_function OF cl_salv_events
        IMPORTING
            e_salv_function
            sender.
ENDCLASS.

CLASS lcl_events IMPLEMENTATION.

  METHOD on_button_click.

    TRY.
        IF o_tree IS BOUND.
* Unternode (Child) zur akt. geklickten Node holen
          DATA(o_child_node) = o_tree->get_nodes( )->get_node( node_key )->get_first_child( ).

* alle Unternodes durchlaufen und Checkbox der Spalte Carrier setzen
          WHILE o_child_node IS BOUND.

            DATA(o_item) = o_child_node->get_item( 'CARRID' ).

            IF o_item->is_checked( ) = abap_true.
              o_item->set_checked( abap_false ).
            ELSE.
              o_item->set_checked( abap_true ).
            ENDIF.

            o_child_node = o_child_node->get_next_sibling( ).
          ENDWHILE.

        ENDIF.
      CATCH cx_salv_msg.
    ENDTRY.

  ENDMETHOD.

  METHOD on_user_command.
    MESSAGE e_salv_function TYPE 'I'.
  ENDMETHOD.

ENDCLASS.

START-OF-SELECTION.
* Daten holen
  SELECT * FROM spfli INTO CORRESPONDING FIELDS OF TABLE it_spfli.

  SORT: it_spfli BY carrid.

  TRY.
* Tree-Objekt mit leerer Tabelle (Dummy) erzeugen
      cl_salv_tree=>factory( IMPORTING
                               r_salv_tree = o_tree
                             CHANGING
                               t_table     = it_spfli_empty ).

* Header setzen
      o_tree->get_tree_settings( )->set_header( CONV #( sy-title ) ).
      o_tree->get_tree_settings( )->set_hierarchy_header( 'Carrier' ).
      o_tree->get_tree_settings( )->set_hierarchy_tooltip( 'Carrier' ).
      o_tree->get_tree_settings( )->set_hierarchy_size( 40 ).
      o_tree->get_tree_settings( )->set_hierarchy_icon( CONV #( icon_tree ) ).

* Treenodes einfügen
      LOOP AT it_spfli ASSIGNING FIELD-SYMBOL(<c>) GROUP BY <c>-carrid.

        DATA(it_cp) = VALUE ty_it_spfli( FOR <cp> IN GROUP <c> ( <cp> ) ).

        DATA(o_parent) = o_tree->get_nodes( )->add_node( related_node   = ''
                                                         relationship   = cl_gui_column_tree=>relat_last_child
                                                         collapsed_icon = CONV #( icon_closed_folder )
                                                         expanded_icon  = CONV #( icon_open_folder )
                                                         row_style      = if_salv_c_tree_style=>intensified
                                                         text           = CONV #( <c>-carrid ) ).

        IF lines( it_cp ) > 1.
          o_parent->get_item( 'CARRID' )->set_type( if_salv_c_item_type=>button ).
          o_parent->get_item( 'CARRID' )->set_value( 'all' ).
        ENDIF.

        LOOP AT GROUP <c> ASSIGNING FIELD-SYMBOL(<f>).
          DATA(o_carrid) = o_tree->get_nodes( )->add_node( related_node = o_parent->get_key( )
                                                           relationship = cl_gui_column_tree=>relat_last_child
                                                           data_row     = <f>
                                                           row_style    = if_salv_c_tree_style=>intensified
                                                           text         = CONV #( <f>-connid ) ).

          o_carrid->get_item( 'CARRID' )->set_type( if_salv_c_item_type=>checkbox ).
          o_carrid->get_item( 'CARRID' )->set_editable( abap_true ).
        ENDLOOP.

      ENDLOOP.

* Mandant ausblenden
      o_tree->get_columns( )->get_column( 'MANDT' )->set_technical( abap_true ).
* Carrid zentriert
      o_tree->get_columns( )->get_column( 'CARRID' )->set_alignment( if_salv_c_alignment=>right ).

* Spaltenbreiten optimieren
      o_tree->get_columns( )->set_optimize( abap_true ).

* Flugzeiten Aggregieren
      o_tree->get_aggregations( )->add_aggregation( columnname  = 'FLTIME'
                                                    aggregation = if_salv_c_aggregation=>total ).

* Alle Funktionsbuttons einschalten
      o_tree->get_functions( )->set_all( abap_true ).

* eigenen 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_tree->get_functions( )->add_function( name     = 'BTN_USR'
*                                              icon     = CONV #( icon_abap )
*                                              text     = 'Testbutton'
*                                              tooltip  = 'Testbutton'
*                                              position = if_salv_c_function_position=>right_of_salv_functions ).

* Handler für Button-Click setzen
      SET HANDLER lcl_events=>on_button_click FOR o_tree->get_event( ).
*      SET HANDLER lcl_events=>on_user_command FOR o_tree->get_event( ).

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

[ABAP] ALV-Grid: Dropdown-Liste verwenden

**********************************************************************
*
* Variablen
*
**********************************************************************
DATA: gv_screen_status TYPE string VALUE 'INIT'.
DATA: gv_carrid TYPE spfli-carrid.
DATA: gv_connid TYPE spfli-connid.
DATA: o_alv TYPE REF TO cl_gui_alv_grid.
DATA: it_spfli TYPE STANDARD TABLE OF spfli WITH DEFAULT KEY.
**********************************************************************
*
* leeres Dynpro als Dummy für ALV-Grid
*
**********************************************************************
SELECTION-SCREEN BEGIN OF SCREEN 2000.
SELECTION-SCREEN END OF SCREEN 2000.
**********************************************************************
*
* SELECTION-SCREEN
*
**********************************************************************
SELECT-OPTIONS: so_carr FOR gv_carrid.
SELECT-OPTIONS: so_conn FOR gv_connid.
**********************************************************************
*
* Eventhandler
*
**********************************************************************
CLASS lcl_events DEFINITION.

  PUBLIC SECTION.

    CLASS-METHODS:
      on_toolbar FOR EVENT toolbar OF cl_gui_alv_grid
        IMPORTING
            e_object
            e_interactive
            sender.

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

CLASS lcl_events IMPLEMENTATION.

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

* Änderungswert in die Zelle der iTab (it_mara) rückschreiben
        <fs_mara_field> = <fs_changed>-value.
      ENDIF.

    ENDLOOP.

* DB Update
    FIELD-SYMBOLS: <fs_tab> TYPE table.
    FIELD-SYMBOLS: <fs_row> TYPE spfli.

    ASSIGN er_data_changed->mp_mod_rows->* TO <fs_tab>.

    LOOP AT <fs_tab> ASSIGNING <fs_row>.
* DB Update hier
    ENDLOOP.

  ENDMETHOD.

  METHOD on_toolbar.
* alle Buttons entfernen, bis auf folgende:
    DELETE e_object->mt_toolbar WHERE
        function NE cl_gui_alv_grid=>mc_fc_refresh          " Refresh
    AND function NE cl_gui_alv_grid=>mc_mb_export           " Excel
    AND function NE cl_gui_alv_grid=>mc_fc_current_variant. " Layout

  ENDMETHOD.
ENDCLASS.
**********************************************************************
*
* INITIALIZATION
*
**********************************************************************
INITIALIZATION.

* Vorbelegungen für Selektionsbild
  so_carr[] = VALUE #( ( sign = 'I' option = 'EQ' low = 'LH' ) ).

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

* Wenn vorher das Selektionsbild 1000 angezeigt wurde
  IF gv_screen_status = 'IN_SELECTION'.
* Daten holen
    SELECT * FROM spfli INTO TABLE @it_spfli
       WHERE carrid IN @so_carr
         AND connid IN @so_conn.
* ALV-Gitter anzeigen
    o_alv = NEW #( i_parent      = cl_gui_container=>default_screen
                   i_appl_events = abap_true ).

* Eventhandler registrieren
    SET HANDLER lcl_events=>on_toolbar FOR o_alv.
    SET HANDLER lcl_events=>on_data_changed FOR o_alv.

* Ereignisse registrieren
    o_alv->register_edit_event( i_event_id = cl_gui_alv_grid=>mc_evt_enter ).
    o_alv->register_edit_event( i_event_id = cl_gui_alv_grid=>mc_evt_modified ).

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

* Layout des ALV setzen
    DATA(lv_layout) = VALUE lvc_s_layo( zebra      = abap_true
                                        cwidth_opt = 'A'
                                        grid_title = 'Flugverbindungen' ).

* Feldkatalog automatisch durch SALV erstellen lassen
    DATA: o_salv TYPE REF TO cl_salv_table.

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

    DATA(it_fcat) = cl_salv_controller_metadata=>get_lvc_fieldcatalog( r_columns      = o_salv->get_columns( )
                                                                       r_aggregations = o_salv->get_aggregations( ) ).

* Drop-Down-Liste definieren und an das ALV-Gitter übergeben
    DATA(it_dropdown) = VALUE lvc_t_drop( ( handle = 1
                                            value  = 'BERLIN' )
                                          ( handle = 1
                                            value  = 'FRANKFURT' )
                                          ( handle = 1
                                            value  = 'NEW YORK' ) ).

    o_alv->set_drop_down_table( it_drop_down = it_dropdown ).

* im Feldkatalog alle Zellen der Spalte "CITYFROM" des ALV-Grids auf
* editierbar stellen, die restlichen Zellen sind nicht editierbar
    LOOP AT it_fcat ASSIGNING FIELD-SYMBOL(<fcat>).
      CASE <fcat>-fieldname.
        WHEN 'CITYFROM'.
          <fcat>-edit = abap_true.
          <fcat>-drdn_hndl = 1.      " Drop-Down-Liste mit Handle = 1 für die Zelle setzen
          <fcat>-outputlen = 10.
        WHEN OTHERS.
          <fcat>-edit = abap_false.
      ENDCASE.
    ENDLOOP.

* ALV anzeigen
    o_alv->set_table_for_first_display( EXPORTING
                                          i_bypassing_buffer = abap_false
                                          i_save             = 'A'
                                          is_layout          = lv_layout
                                        CHANGING
                                          it_fieldcatalog    = it_fcat
                                          it_outtab          = it_spfli ).

* Focus auf ALV setzen
    cl_gui_alv_grid=>set_focus( control = o_alv ).

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

* Flag für Screen-Status auf ALV-Anzeige setzen
    gv_screen_status = 'IN_ALV'.
  ENDIF.
**********************************************************************
*
* START-OF-SELECTION
*
**********************************************************************
START-OF-SELECTION.

* Wir befinden uns im Anzeigebereich des Selektionsbildes
  gv_screen_status = 'IN_SELECTION'.

* Trick: leeren Dummy-Screen 2000 anzeigen und intern für das ALV-Grid in
* AT SELECTION-SCREEN OUTPUT als cl_gui_container=>default_screen nutzen
  CALL SELECTION-SCREEN 2000.

[ABAP] SALV-Table – Aggregationsfunktionen

DATA: o_alv TYPE REF TO cl_salv_table.

...

* vorher sortieren und subtotal setzen
o_alv->get_sorts( )->add_sort( columnname = 'CARRID' subtotal = abap_true ).

* Aggregation
o_alv->get_aggregations( )->add_aggregation( columnname  = 'PAYMENTSUM'                    " für Spalte 'PAYMENTSUM'
                                             aggregation = if_salv_c_aggregation=>total ). " Summe bilden