SALV Table 21 – Editable with Single (custom) Method

By | June 29, 2015 | SALV Table, SALV Tutorial | 18,419 | 0

Another of my recently published blog on SCN. This is also about making SALV table editable using the single method and removing the extra button.

Originally published on SCN – SALV Editable with Single (custom) Method

This has been a SALV Editable week. Earlier this week, I published a blog on standard application using SALV for editable(SALV Editable? Yes, as per this Standard SAP Application)

The solution works great if there is an extra button. This extra button – say Edit – would make the SALV editable. This button is required to gain the access of the underlying Grid object (CL_GUI_ALV_GRID). The Grid object than used to set up the editable functionality. Paul Hardy had asked if we can remove that extra button and make the SALV editable directly, in his comment section of my previous blog SALV Editable? Yes, as per this Standard SAP Application

No more button

The idea was to find an event which gets triggered but before the output is displayed to the user. I did some research, infect lot of research to find an event that would work in both Grid and FullScreen ALV. I played with different events like TOP_OF_PAGE, TOP_OF_LIST, PRINT_TOP_OF_PAGE etc.

Fullscreen ALV triggers TOP_OF_PAGE but not the Grid ALV, as for Grid there is no direct TOP_OF_PAGE. FullScreen ALV triggers it when the top of page is created using the method O_SALV->SET_TOP_OF_LIST( ). Also this would bring up a header in the ALV. For the Grid, You would need to create an object for CL_DD_DOCUMENT, pass it to the Grid object and raise the event TOP_OF_PAGE. Without having the Grid to begin with, can’t assign the header, and thus can’t get the TOP_OF_PAGE event to work.

Event AFTER_REFRESH is the trick, I was looking for 🙂

SALV_Editable_0

Event AFTER_REFRESH

Event AFTER_REFRESH gets triggered after system finished rendering ALV – Field catalog parsed, Data sent to the DP (data provider) aka Frontend, Layout applied, Toolbar created, and all other ALV related stuff. Now, how to capture this event when there is no Grid object. So, declared an event handler to handle the event AFTER_REFRESH of class CL_GUI_ALV_GRID. The trick is the registration of the event using the addition FOR ALL INSTANCES of SET EVENT HANDLER.

 
  "To gain an access to the underlying object and
  "  do the magic
  SET HANDLER lo_event_h->on_after_refresh
    FOR ALL INSTANCES
    ACTIVATION 'X'.
 

FOR ALL INSTANCES is quite powerful. It can register the event for any object for that event belongs, even if the object is instantiated after the handler is registered. That’s very useful in this scenario as the Grid object is not yet instantiated.

Avoid Endless Loop Trap

To make the grid editable, either you can pass the LAYOUT-EDIT = ‘X’ with following REFRESH_TABLE_DISPLAY( ) call or method SET_READY_FOR_INPUT call . The thing is, both of these methods would call the method SOFT_REFRESH_TABLE_DISPLAY and would raise the event AFTER_REFRESH. This would again be caught in our event handler. The event handler would make the grid editable again with refresh – so going in the loop.

To avoid this, we would switch off – more technically deregister the event handler. Using the addition ACTIVATION space in the SET HANDLER would do this for us.

 
    "deregister the event handler
    SET HANDLER me->on_after_refresh
      FOR ALL INSTANCES
      ACTIVATION space.
 

Toolbar

Next is the toolbar. The edit buttons in the toolbar are displayed without any additional work, but for grid there is some special logic which prevents it from creating the edit buttons in the toolbar. This all happens in the method CL_SALV_CONTROLLER_EVENTS=> RAISE_BUILD_UIFUNCTION where only few of the buttons are displayed.

So we will trick the toolbar to add the same missing buttons. To do this, we would need to register the event TOOLBAR for the CL_GUI_ALV_GRID. This would be done same – with using the FOR ALL INSTANCE.

  "only for GRID, would need to add the toolbar buttons
  IF io_salv->get_display_object( ) = 3.
    SET HANDLER lo_event_h->on_toolbar
      FOR ALL INSTANCES
      ACTIVATION 'X'.
  ENDIF.
 

Single Method to Make it Editable

Not out of the box single method :), but I enclosed all these logic in one single method. Call this method by passing the ALV object before the DISPLAY method, and all done.

The method would register the event AFTER_REFRESH and TOOLBAR (for grid). The class also host the event handler methods in the local class. The event handler would make the grid editable and add the buttons in the toolbar as well. All the complexity for making it editable is hidden and wrapped in this method.

Also this method would control the logic for multiple SALV objects. Optional parameter SENDER for the event handler with the object pool design pattern is used.

" Make grid editable
" call before display
  zcl_test_np_salv_model=>set_editable( gr_table ).
 
 

In Action

Fullscreen ALV generated by SALV in Editable mode

SALV_Editable_2

ALV Grid generated by SALV in Editable mode

SALV_Editable_2_0

Multiple Grid, only one is editable

SALV_Editable_1

Full Method Code

Here is the method ZCL_TEST_NP_SALV_MODEL=>SET_EDITABLE

class ZCL_TEST_NP_SALV_MODEL definition
  public
  final
  create public .
 
public section.
  class-methods SET_EDITABLE
    importing
      !IO_SALV type ref to CL_SALV_TABLE .
  PROTECTED SECTION.
  PRIVATE SECTION.
    class-data o_event_h type ref to OBJECT.
ENDCLASS.
 
 
CLASS ZCL_TEST_NP_SALV_MODEL IMPLEMENTATION.
* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Static Public Method ZCL_TEST_NP_SALV_MODEL=>SET_EDITABLE
* +-------------------------------------------------------------------------------------------------+
* | [--->] IO_SALV                        TYPE REF TO CL_SALV_TABLE
* +-------------------------------------------------------------------------------------</SIGNATURE>
METHOD set_editable.
 
  DATA: lo_event_h TYPE REF TO lcl_event_handler.
 
  "Event handler
  IF zcl_test_np_salv_model=>o_event_h IS NOT BOUND.
    CREATE OBJECT zcl_test_np_salv_model=>o_event_h
      TYPE lcl_event_handler.
  ENDIF.
 
  lo_event_h ?= zcl_test_np_salv_model=>o_event_h.
  APPEND io_salv TO lo_event_h->t_salv.
 
  "To gain an access to the underlying object and
  "  do the magic
  SET HANDLER lo_event_h->on_after_refresh
    FOR ALL INSTANCES
    ACTIVATION 'X'.
 
  "only for GRID, would need to add the toolbar buttons
  IF io_salv->get_display_object( ) = 3.
    SET HANDLER lo_event_h->on_toolbar
      FOR ALL INSTANCES
      ACTIVATION 'X'.
  ENDIF.
 
ENDMETHOD.
ENDCLASS.
 

And the event handler LCL_EVENT_HANDLER

 
*----------------------------------------------------------------------*
* Event handler ALV events
*----------------------------------------------------------------------*
CLASS lcl_event_handler DEFINITION.
  PUBLIC SECTION.
    METHODS:
      on_after_refresh FOR EVENT after_refresh OF cl_gui_alv_grid
        IMPORTING
          sender,
      on_toolbar      FOR EVENT toolbar      OF cl_gui_alv_grid
        IMPORTING
          e_object
          e_interactive
          sender.
    DATA: t_salv TYPE STANDARD TABLE OF REF TO cl_salv_table.
ENDCLASS.                    "lcl_event_handler DEFINITION
*
CLASS lcl_event_handler IMPLEMENTATION.
  METHOD on_after_refresh.
    DATA: lo_grid TYPE REF TO cl_gui_alv_grid.
    DATA: ls_layout TYPE lvc_s_layo.
    DATA: lo_salv TYPE REF TO cl_salv_table.
 
    TRY .
        LOOP AT t_salv INTO lo_salv.
          lo_grid = zcl_test_np_salv_model=>get_grid( lo_salv ).
          CHECK lo_grid EQ sender.
 
          "deregister the event handler
          SET HANDLER me->on_after_refresh
            FOR ALL INSTANCES
            ACTIVATION space.
 
          "Set editable
          ls_layout-edit = 'X'.
          lo_grid->set_frontend_layout( ls_layout ).
          lo_grid->set_ready_for_input( 1 ).
        ENDLOOP.
      CATCH cx_salv_error.
    ENDTRY.
  ENDMETHOD.                    "on_AFTER_REFRESH
*
  METHOD on_toolbar.
 
    DATA: lo_grid TYPE REF TO cl_gui_alv_grid.
    DATA: ls_layout TYPE lvc_s_layo.
    DATA: mt_toolbar TYPE ttb_button.
    DATA: ls_toolbar LIKE LINE OF mt_toolbar.
    DATA: lo_salv TYPE REF TO cl_salv_table.
 
 
    TRY .
        LOOP AT t_salv INTO lo_salv.
          lo_grid = zcl_test_np_salv_model=>get_grid( lo_salv ).
          IF lo_grid EQ sender.
            EXIT.
          ELSE.
            CLEAR lo_grid.
          ENDIF.
        ENDLOOP.
      CATCH cx_salv_msg.
        EXIT.
    ENDTRY.
 
    CHECK lo_grid IS BOUND.
    CHECK lo_grid->is_ready_for_input( ) = 1.
 
 
*... Toolbar Button CHECK
    CLEAR ls_toolbar.
    ls_toolbar-function    = cl_gui_alv_grid=>mc_fc_check.
    ls_toolbar-quickinfo  = text-053.  "Eingaben prfen
    ls_toolbar-icon        = icon_check.
    ls_toolbar-disabled    = space.
    APPEND ls_toolbar TO mt_toolbar.
 
 
*... Toolbar Seperator
    CLEAR ls_toolbar.
    ls_toolbar-function    = '&&SEP01'.
    ls_toolbar-butn_type  = 3.
    APPEND ls_toolbar TO mt_toolbar.
 
*... Toolbar Button CUT
    CLEAR ls_toolbar.
    ls_toolbar-function    = cl_gui_alv_grid=>mc_fc_loc_cut.
    ls_toolbar-quickinfo  = text-046.  "Ausschneiden
    ls_toolbar-icon        = icon_system_cut.
    ls_toolbar-disabled    = space.
    APPEND ls_toolbar TO mt_toolbar.
 
*... Toolbar Button COPY
    CLEAR ls_toolbar.
    ls_toolbar-function    = cl_gui_alv_grid=>mc_fc_loc_copy.
    ls_toolbar-quickinfo  = text-045.                        " Kopieren
    ls_toolbar-icon        = icon_system_copy.
    ls_toolbar-disabled    = space.
    APPEND ls_toolbar TO mt_toolbar.
 
*... Toolbar Button PASTE OVER ROW
    CLEAR ls_toolbar.
    ls_toolbar-function    = cl_gui_alv_grid=>mc_fc_loc_paste.
    ls_toolbar-quickinfo  = text-047.
    ls_toolbar-icon        = icon_system_paste.
    ls_toolbar-disabled    = space.
    APPEND ls_toolbar TO mt_toolbar.
 
*... Toolbar Button PASTE NEW ROW
    CLEAR ls_toolbar.
    ls_toolbar-function    = cl_gui_alv_grid=>mc_fc_loc_paste_new_row.
    ls_toolbar-quickinfo  = text-063.
    ls_toolbar-icon        = icon_system_paste.
    ls_toolbar-disabled    = space.
    APPEND ls_toolbar TO mt_toolbar.
 
*... Toolbar Button UNDO
    CLEAR ls_toolbar.
    ls_toolbar-function    = cl_gui_alv_grid=>mc_fc_loc_undo.
    ls_toolbar-quickinfo  = text-052.  "Rckgngig
    ls_toolbar-icon        = icon_system_undo.
    ls_toolbar-disabled    = space.
    APPEND ls_toolbar TO mt_toolbar.
 
*... Toolbar Separator
    CLEAR ls_toolbar.
    ls_toolbar-function    = '&&SEP02'.
    ls_toolbar-butn_type  = 3.
    APPEND ls_toolbar TO mt_toolbar.
 
*... Toolbar Button APPEND ROW
    CLEAR ls_toolbar.
    ls_toolbar-function    = cl_gui_alv_grid=>mc_fc_loc_append_row.
    ls_toolbar-quickinfo  = text-054.  "Zeile anhngen
    ls_toolbar-icon        = icon_create.
    ls_toolbar-disabled    = space.
    APPEND ls_toolbar TO mt_toolbar.
 
*... Toolbar Button INSERT ROW
    CLEAR ls_toolbar.
    ls_toolbar-function    = cl_gui_alv_grid=>mc_fc_loc_insert_row.
    ls_toolbar-quickinfo  = text-048.  "Zeile einfgen
    ls_toolbar-icon        = icon_insert_row.
    ls_toolbar-disabled    = space.
    APPEND ls_toolbar TO mt_toolbar.
 
*... Toolbar Button DELETE ROW
    CLEAR ls_toolbar.
    ls_toolbar-function    = cl_gui_alv_grid=>mc_fc_loc_delete_row.
    ls_toolbar-quickinfo  = text-049.  "Zeile lschen
    ls_toolbar-icon        = icon_delete_row.
    ls_toolbar-disabled    = space.
    APPEND ls_toolbar TO mt_toolbar.
 
*... Toolbar Button COPY ROW
    CLEAR ls_toolbar.
    ls_toolbar-function    = cl_gui_alv_grid=>mc_fc_loc_copy_row.
    ls_toolbar-quickinfo  = text-051.  "Duplizieren
    ls_toolbar-icon        = icon_copy_object.
    ls_toolbar-disabled    = space.
    APPEND ls_toolbar TO mt_toolbar.
 
*... Toolbar Separator
    CLEAR ls_toolbar.
    ls_toolbar-function    = '&&SEP03'.
    ls_toolbar-butn_type  = 3.
    APPEND ls_toolbar TO mt_toolbar.
 
    APPEND LINES OF mt_toolbar TO e_object->mt_toolbar.
 
  ENDMETHOD.                    "on_toolbar
ENDCLASS.                    "lcl_event_handler IMPLEMENTATION
 

Originally published on SCN – SALV Editable with Single (custom) Method

Like It? Share!!

Don't miss an Update

Get notified of the new post, right into your inbox

Naimesh Patel{274 articles}

I'm SAP ABAP Consultant for more than a decade. I like to experiment with ABAP especially OO. I have been SDN Top Contributor.
Follow :

Explore all of his 274 articles.

Load comments

Comments on this Post are now closed. If you have something important to share, you can always contact me.

You seem to be new here. Subscribe to stay connected.