Standard 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.