ABAP – ALV Context menu + keep row selection after a filter is applied

SAPStandard functionality of an ALV grid offers row selection by clicking on the row headers. You can also use Ctrl or Shift keys to do mutliple row selection. Drawback of this is when you need to select some rows and apply some filters at the same time. Setting or deleting filter (or any operation which does grid refresh) clears the row selection. If you need to keep the row selection together with functionality of filter (and others), you can follow my little suggestion

The idea is simple – extend the selection model with separate column to hold the selected/not-selected information. It can be interpreted as a checkbox for example.

Selection of rows can now be made either by clicking on check boxes OR by clicking on the row headers + applying a context menu action.

Here I’ll provide a sample code how to achieve this.

Prerequisites:

  • I have a Z-program where I implement local class handling the ALV
  • In SE80 I created screen 0100 for this program

Note:

  • I’ll show a demo for simple field catalog (material and plant columns)
  • Data loading is faked (hard coded values) to limit complexity of the code

Structure of data in ALV grid:

TYPES:
  BEGIN OF gty_data,
    selected TYPE char1,
    matnr TYPE matnr,
    plant TYPE werks_d,
  END OF gty_data.

Global data and PBO code for screen 0100:

DATA:
  gr_grid TYPE REF TO lcl_demo.

START-OF-SELECTION.
  CALL SCREEN 100.

MODULE pbo_0100 OUTPUT.
  CREATE OBJECT gr_grid.
  gr_grid->show_grid( ).
ENDMODULE.

Class definition:

CLASS lcl_demo DEFINITION.
  PUBLIC SECTION.
    METHODS show_grid.

  PRIVATE SECTION.
    DATA:
      mt_fieldcat TYPE lvc_t_fcat,        
      mo_data_grid TYPE REF TO cl_gui_alv_grid,
      mt_data TYPE STANDARD TABLE OF gty_data WITH KEY matnr.

    CONSTANTS:
*     Functions used in the context menu
      BEGIN OF mc_functions,
        select_rows              TYPE ui_func VALUE 'SELECT_ROWS',
        unselect_rows            TYPE ui_func VALUE 'UNSELECT_ROWS',
      END OF mc_functions.

*   Own method for handling ALV context menu request
    METHODS my_ctx_menu_request_handler      " CONTEXT_MENU_REQUEST
       FOR EVENT context_menu_request OF cl_gui_alv_grid
         IMPORTING
           e_object.

*   Own method for handling user command sent from context menu
    METHODS my_user_command_handler                 " USER_COMMAND
       FOR EVENT user_command OF cl_gui_alv_grid
         IMPORTING
           e_ucomm.

    METHODS set_rows_selected
      IMPORTING is_selected TYPE abap_bool.
    METHODS build_fieldcat.
    METHODS load_data.
ENDCLASS.

Implementation of the class:

CLASS lcl_demo IMPLEMENTATION.
  METHOD build_fieldcat.
    FIELD-SYMBOLS:
      <fs_fcat> TYPE lvc_s_fcat.

*   Checkbox column used to determine if a row is selected
    APPEND INITIAL LINE TO mt_fieldcat ASSIGNING <fs_fcat>.
    <fs_fcat>-fieldname = 'SELECTED'.
    <fs_fcat>-checkbox  = abap_true.
    <fs_fcat>-edit      = abap_true.
    <fs_fcat>-scrtext_s = 'Selected'.
    <fs_fcat>-outputlen = 5.

    APPEND INITIAL LINE TO mt_fieldcat ASSIGNING <fs_fcat>.
    <fs_fcat>-fieldname = 'MATNR'.
    <fs_fcat>-scrtext_s = 'Material'.

    APPEND INITIAL LINE TO mt_fieldcat ASSIGNING <fs_fcat>.
    <fs_fcat>-fieldname = 'PLANT'.
    <fs_fcat>-scrtext_s = 'Plant'.
  ENDMETHOD.                    "build_fieldcat

* Method to load data for ALV grid
  METHOD load_data.
    FIELD-SYMBOLS:
      <fs_data> TYPE gty_data.

    APPEND INITIAL LINE TO mt_data ASSIGNING <fs_data>.
    <fs_data>-matnr = 123456.
    <fs_data>-plant = 'P001'.

    APPEND INITIAL LINE TO mt_data ASSIGNING <fs_data>.
    <fs_data>-matnr = 654321.
    <fs_data>-plant = 'P999'.
  ENDMETHOD.                    "load_data

  METHOD show_grid.
    DATA:
      ls_layout   TYPE lvc_s_layo.

    IF mo_data_grid IS INITIAL.
*     Create the ALV grid object using the whole screen
*     as container
      CREATE OBJECT mo_data_grid
        EXPORTING
          i_parent      = cl_gui_container=>screen0
          i_appl_events = abap_true.

      ls_layout-sel_mode = 'A'.
      ls_layout-no_rowmark = abap_false.

      me->build_fieldcat( ).
      me->load_data( ).

*     Register handler for context menu request
      SET HANDLER my_ctx_menu_request_handler FOR mo_data_grid.

*     Register handler for user action in context menu
      SET HANDLER my_user_command_handler FOR mo_data_grid.

*     Display the ALV grid
      mo_data_grid->set_table_for_first_display(
        EXPORTING
          is_layout             = ls_layout
        CHANGING
          it_fieldcatalog       = mt_fieldcat
          it_outtab             = mt_data ).
    ENDIF.
  ENDMETHOD.                    "show_grid

* Implementation of the context menu request
  METHOD my_ctx_menu_request_handler.
    DATA:
      ls_row    TYPE lvc_s_row,
      ls_col    TYPE lvc_s_col.
*   Get cell which was clicked
    CALL METHOD mo_data_grid->get_current_cell
      IMPORTING
        es_row_id = ls_row
        es_col_id = ls_col.

*   Add ctx-menu items only if clicked on row header where
*   FIELDNAME is initial
    CHECK ls_col-fieldname IS INITIAL.

*   Adding custom functions
    CALL METHOD e_object->add_function
      EXPORTING
        fcode = mc_functions-select_rows
        text  = 'Select highlighted rows'.

    CALL METHOD e_object->add_function
      EXPORTING
        fcode = mc_functions-unselect_rows
        text  = 'Unselect highlighted rows'.
  ENDMETHOD.                    "my_context_menu_request_handler

* Set the selected rows checked or unchecked 
* modifies the first column
  METHOD set_rows_selected.
    DATA:
    lt_selected_rowids TYPE lvc_t_roid.

    FIELD-SYMBOLS:
      <fs_data> TYPE gty_data,
      <fs_selrow> TYPE lvc_s_roid.

*   Get selected rows (using row headers)
    CALL METHOD mo_data_grid->get_selected_rows
      IMPORTING
        et_row_no = lt_selected_rowids.

*   Modify ALV grid data - first column
    LOOP AT lt_selected_rowids ASSIGNING <fs_selrow>.
      READ TABLE mt_data ASSIGNING <fs_data> INDEX <fs_selrow>-row_id.
      CHECK sy-subrc = 0.
      <fs_data>-selected = is_selected.
    ENDLOOP.
  ENDMETHOD.                    "set_rows_selected

* Method to handle response on user actions in context menu
  METHOD my_user_command_handler.
    CASE e_ucomm.
      WHEN mc_functions-select_rows.
        set_rows_selected( abap_true ).

      WHEN mc_functions-unselect_rows.
        set_rows_selected( abap_false ).
    ENDCASE.
    IF mo_data_grid IS NOT INITIAL.
      mo_data_grid->refresh_table_display( ).
    ENDIF.
  ENDMETHOD.                    "my_user_command_handler
ENDCLASS.

Output:
ALV Context menu

Leave a Reply