[ABAP] GUI Containertypen

cl_gui_container

* cl_gui_container=>default_screen
* cl_gui_container=>screen0 ... cl_gui_container=>screen9
  • Fullscreen-Container der Listenausgabe
  • Erzeugung erfolgt z.B. bei WRITE (Bsp.: WRITE space.)
  • können als Basis für weitere Container genommen werden

Beispiel für cl_gui_container: Link

cl_gui_splitter_container

  • Splitter mit Subcontainern
  • benötigt Parent (z.B. cl_gui_container=>screen0, cl_gui_docking_container, cl_gui_custom_container)

Beispiel für cl_gui_splitter_container: Link

cl_gui_docking_container

  • Dock-Seite kann angegeben werden
  • Breite / Höhe kann absolut (extension) oder relativ (ratio) angegeben werden

Beispiel für cl_gui_docking_container: Link

cl_gui_dialogbox_container

  • erzeugt ein neues eigenständiges Fenster
  • Event “on_close” sollte behandelt werden, damit auf das Schließen-Kreuz reagiert werden kann

Beispiel für cl_gui_dialogbox_container: Link

cl_gui_custom_container

  • Containerobjekt zur Verwendung auf Dynpros
  • ein Name muss vergeben werden

Beispiel für cl_gui_custom_container: Link

cl_gui_gos_container

  • Containerobjekt für Anzeige von Generic Object Services (GOS) in der Titlebar
  • beliebige Untercontainer können eingebettet werden

Beispiel für cl_gui_gos_container: Link

cl_gui_container_bar

  • vertikales Tabstrip mit Auswahl-Buttons

Beispiel für cl_gui_container_bar: Link

cl_gui_container_bar_2

  • vertikales Tabstrip mit Auswahl-Buttons und Schließen-Kreuz
  • drei Anzeigemodi (fix (Feste Anordnung), tile (Menü), outlook (Anordnung klappt))

Beispiel für cl_gui_container_bar_2: Link

cl_gui_container_bar_xt

  • vertikales Tabstrip mit Auswahl-Buttons und Schließen-Kreuz
  • zwei Anzeigemodi (fix (Feste Anordnung), outlook (Anordnung klappt))

Beispiel für cl_gui_container_bar_xt: Link

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

[ABAP] ALV-Grid ohne Dynpro – Daten anzeigen, editieren und als CSV-Datei speichern

DATA: it_mara TYPE STANDARD TABLE OF mara.

CLASS lcl_events DEFINITION.

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

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

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

CLASS lcl_events IMPLEMENTATION.
* 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 = 'Edit' icon = icon_change_text function = 'EDIT_DATA' quickinfo = 'Editieren' disabled = ' ' ) TO e_object->mt_toolbar.
* Speichern-Button hinzufügen
    APPEND VALUE #( butn_type = 5 text = 'Speichern' icon = icon_system_save function = 'SAVE_DATA' quickinfo = 'Speichern' disabled = ' ' ) TO e_object->mt_toolbar.
  ENDMETHOD.

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

        IF <f> IS ASSIGNED.
* Änderungswert in die Zelle der iTab (it_mara) rückschreiben
          <f> = <c>-value.
        ENDIF.
      ENDIF.
    ENDLOOP.

  ENDMETHOD.
* Benutzerkommandos behandeln
  METHOD on_user_command.
    CASE e_ucomm.
* Daten speichern
      WHEN 'SAVE_DATA'.
        DATA: lv_action TYPE i.
        DATA: lv_filename TYPE string.
        DATA: lv_fullpath TYPE string.
        DATA: lv_path TYPE string.
* FileSave-Dialog aufrufen
        TRY.
            cl_gui_frontend_services=>file_save_dialog( EXPORTING
                                                          default_extension   = 'txt'
                                                          file_filter         = |TXT (*.txt)\|*.txt\|{ cl_gui_frontend_services=>filetype_all }|
                                                          prompt_on_overwrite = abap_true
                                                        CHANGING
                                                          filename            = lv_filename     " Dateiname
                                                          path                = lv_path         " Pfad
                                                          fullpath            = lv_fullpath     " Pfad + Dateiname
                                                          user_action         = lv_action ).    " Benutzeraktion

            IF lv_action EQ cl_gui_frontend_services=>action_ok.
* iTab nach CSV konvertieren und speichern
              cl_icf_csv=>request_for_write_into_csv( it_data            = it_mara
                                                      iv_hdr_struct_name = 'MARA'
                                                      iv_init_dir        = lv_path
                                                      iv_file_name       = lv_filename ).

              MESSAGE 'Daten erfolgreich gespeichert.' TYPE 'I'.
            ENDIF.

          CATCH cx_root INTO DATA(e_text).          " Oberklasse für Exceptions abfangen und Kurztext übergeben
            MESSAGE e_text->get_text( ) TYPE 'I'.   " Exception Kurztext ausgeben
        ENDTRY.

* Editmodus umschalten
      WHEN 'EDIT_DATA'.
        DATA: it_fcat TYPE lvc_t_fcat.
        DATA: lv_edit TYPE abap_bool VALUE abap_false.

* Feldkatalog holen
        sender->get_frontend_fieldcatalog( IMPORTING
                                             et_fieldcatalog = it_fcat ).

        IF lines( it_fcat ) > 0.
          lv_edit = it_fcat[ 1 ]-edit.
        ENDIF.

        CASE lv_edit.
          WHEN abap_true.
            lv_edit = abap_false.
          WHEN OTHERS.
            lv_edit = abap_true.
        ENDCASE.

* im Feldkatalog alle Zellen des ALV-Grids auf editierbar stellen
        LOOP AT it_fcat ASSIGNING FIELD-SYMBOL(<fcat>).
          <fcat>-edit = lv_edit.
        ENDLOOP.

* Feldkatalog zurückgeben
        sender->set_table_for_first_display( CHANGING
                                              it_fieldcatalog = it_fcat
                                              it_outtab = it_mara ).
    ENDCASE.
  ENDMETHOD.
ENDCLASS.

START-OF-SELECTION.

  SELECT * FROM mara INTO TABLE it_mara UP TO 100 ROWS.

  DATA(o_alv) = NEW cl_gui_alv_grid( 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.
  SET HANDLER lcl_events=>on_user_command FOR o_alv.

  o_alv->register_edit_event( i_event_id = cl_gui_alv_grid=>mc_evt_enter ).

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

  DATA(lv_layout) = VALUE lvc_s_layo( zebra = abap_true
                                      cwidth_opt = 'A'
                                      grid_title = 'Editierbares ALV-Gitter ohne extra Dynpro' ).

  o_alv->set_table_for_first_display( EXPORTING
                                        i_bypassing_buffer = abap_true
                                        i_save             = 'A'
                                        is_layout          = lv_layout
                                        i_structure_name   = 'MARA'
                                      CHANGING
                                        it_outtab        = it_mara ).

  cl_gui_alv_grid=>set_focus( control = o_alv ).

  cl_gui_cfw=>flush( ).

* leere Toolbar ausblenden
  cl_abap_list_layout=>suppress_toolbar( ).

* Listenausgabe für cl_gui_container=>default_screen erzwingen
  WRITE: space.

[ABAP] Nutzung der Google-Chart-API zur Anzeige von Charts

* Beispiel adaptiert von:
* http://www.tricktresor.de/blog/sap-und-bunte-bilder-cl_gui_html_viewer/

DATA: lv_s032 TYPE s032.
SELECT-OPTIONS: so_werks FOR lv_s032-werks.

START-OF-SELECTION.

* Alle Bestände je Werk aus der S032 summieren
  SELECT werks,                    " Werk
         SUM( wbwbest ) AS wbwbest " Summe Wert Bewerteter Bestand
    INTO TABLE @DATA(it_data)
    FROM s032
      WHERE werks IN @so_werks
        AND vrsio = '000'
      GROUP BY werks.

* HTML-Code erzeugen
  DATA(it_html) = VALUE html_table(
                                    ( |<html>| )
                                    ( |  <head>| )
                                    ( |    <script type="text/javascript" src="https://www.google.com/jsapi"></script>| )
                                    ( |    <script type="text/javascript">| )
                                    ( |      google.load("visualization", "1", \{packages:["corechart"]\});| )
                                    ( |      google.setOnLoadCallback(drawChart);| )
                                    ( |      function drawChart() \{| )
                                    ( |        var data = google.visualization.arrayToDataTable([ ['Werk', 'Bestand'],| )
                                  ).

* Daten aus der iTab in den Code einfügen
  DATA(lv_html) = ||.

  LOOP AT it_data ASSIGNING FIELD-SYMBOL(<d>).
    IF lv_html IS INITIAL.
      lv_html = |        ['{ <d>-werks }', { <d>-wbwbest }]|.
    ELSE.
      lv_html = |        ,['{ <d>-werks }', { <d>-wbwbest }]|.
    ENDIF.

    APPEND lv_html TO it_html.
  ENDLOOP.

* Code abschließen
  it_html = VALUE html_table( BASE it_html
                              ( |        ]);| )
                              ( |        var options = \{title: 'Summe bewertete Bestände pro Werk'\};| )
                              ( |        var chart = new google.visualization.PieChart(document.getElementById('piechart'));| )
                              ( |        chart.draw(data, options);| )
                              ( |      \};| )
                              ( |    </script>| )
                              ( |  </head>| )
                              ( |  <body>| )
                              ( |    <div id="piechart" style="width: 900px; height: 500px;"></div>| )
                              ( |  </body>| )
                              ( |</html>| )
                            ).

* HTML-Viewer
  DATA(o_html) = NEW cl_gui_html_viewer( parent = cl_gui_container=>default_screen ).

* URL zu HTML holen
  DATA: lv_url TYPE swk_url.

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

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

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

* Ausgabe von cl_gui_container=>default_screen erzwingen
  WRITE: space.

[ABAP] SALV-Table: Funktionsbuttons hinzufügen

Variante 1 (nur wenn in eigenem Dynpro + Container)

SELECT * FROM sflights INTO TABLE @DATA(it_data).

DATA: o_salv TYPE REF TO cl_salv_table.

cl_salv_table=>factory( EXPORTING
                          r_container  = cl_gui_container=>default_screen " Standard-Container der Listausgabe nutzen
                        IMPORTING
                          r_salv_table = o_salv
                        CHANGING
                          t_table      = it_data ).

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

* Für diesen Button muss zus. noch ein Event-Handler ausgeprägt werden
o_salv->get_functions( )->add_function( name     = 'MYFUNC'
                                        icon     = |{ icon_complete }|
                                        text     = 'Funktionstext'
                                        tooltip  = 'ToolTipText'
                                        position = if_salv_c_function_position=>right_of_salv_functions ).

o_salv->display( ).

* Erzwingen von cl_gui_container=>default_screen (Listausgabe)
WRITE space.

Variante 2 (PF_STATUS)

* ohne Angabe eines Containers in der factory-Methode:
SELECT * FROM sflights INTO TABLE @DATA(it_data).

DATA: o_salv TYPE REF TO cl_salv_table.

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

* PF-Status aus Programm SAPLSLVC_FULLSCREEN benutzen
o_salv->set_screen_status( pfstatus      = 'STANDARD_FULLSCREEN'
                           report        = 'SAPLSLVC_FULLSCREEN'
                           set_functions = cl_salv_model_base=>c_functions_all ).

o_salv->display( ).

oder

SELECT * FROM sflights INTO TABLE @DATA(it_data).

DATA: o_salv TYPE REF TO cl_salv_table.

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

* PF-Status manuelle aus Funktionsgruppe SALV_METADATA_STATUS kopieren
* im lokalen Programm (sy-repid) aufrufen
o_salv->set_screen_status( pfstatus      = 'SALV_TABLE_STANDARD'
                           report        = sy-repid
                           set_functions = cl_salv_model_base=>c_functions_all ).

o_salv->display( ).