In some cases, we might came across a requirement for displaying an ALV Grid in popup screen where we need to select few records and then perform certain function based on selected data. For choosing which function we need to perform, we required custom buttons on the Popup screen. For achieving this requirement, I have created a factory class (ZCL_ALV_POPUP), for using it following things need to be remember:
FACTORY Method:
- It returns the instance of the popup class.
- For data to be displayed in ALV grid we need to pass an internal table in IT_DATA parameter.
- For adding the custom buttons we can pass the PF-Status and its program name and whenever custom button is clicked, it raises an event button_click by exporting function code of button and internal table for selected data.
- For multiple selection of data in ALV, we need to pass IV_MULTI_SELECT as abap_true else abap_false for single selection.
DISPLAY Method:
- For displaying the popup we need to need to pass the coordinates.
CLASS DEFINITION
class ZCL_ALV_POPUP definition
public
final
create private .
public section.
constants MC_FUNC_REFRESH type SALV_DE_FUNCTION value '&REFRS'. "#EC NOTEXT
constants MC_FUNC_SELECTALL type SALV_DE_FUNCTION value '&SELECT'. "#EC NOTEXT
constants MC_FUNC_DESELECTALL type SALV_DE_FUNCTION value '&DESELECT'. "#EC NOTEXT
events BUTTON_CLICK
exporting
value(EV_SALV_FUNCTION) type SALV_DE_FUNCTION
value(ET_SELECTED_DATA) type TABLE .
type-pools ABAP .
methods CONSTRUCTOR
importing
!IT_DATA type TABLE
!IV_PROG_NAME type SYREPID optional
!IV_PF_STATUS type SYPFKEY optional
!IV_MULTI_SELECT type ABAP_BOOL optional .
class-methods FACTORY
importing
!IT_DATA type TABLE
!IV_PROG_NAME type SYREPID optional
!IV_PF_STATUS type SYPFKEY optional
!IV_MULTI_SELECT type ABAP_BOOL default ABAP_TRUE
returning
value(R_ALV_POPUP) type ref to ZCL_ALV_POPUP .
methods DISPLAY
importing
!IV_START_COLUMN type I
!IV_START_LINE type I
!IV_END_COLUMN type I optional
!IV_END_LINE type I optional .
PROTECTED SECTION.
DATA mr_alv_data TYPE REF TO data . METHODS assign_alv_data
PRIVATE SECTION.
DATA mr_table_type TYPE REF TO cl_abap_tabledescr .
DATA mr_alv TYPE REF TO cl_salv_table .
DATA mv_multi_select TYPE abap_bool .
DATA mv_prog_name TYPE syrepid .
DATA mv_pf_status TYPE sypfkey .
IMPORTING
!it_data TYPE table
EXPORTING
!er_data TYPE REF TO data
!er_table_type TYPE REF TO cl_abap_tabledescr .
METHODS get_selected_data
EXPORTING
value(et_data) TYPE table .
METHODS select_all
IMPORTING
!iv_value TYPE abap_bool DEFAULT abap_true .
METHODS on_link_click
FOR EVENT link_click OF cl_salv_events_table
IMPORTING
!row
!column .
METHODS on_user_command
FOR EVENT added_function OF cl_salv_events
IMPORTING
!e_salv_function .
ENDCLASS.
CLASS IMPLEMENTATION
CLASS ZCL_ALV_POPUP IMPLEMENTATION.
* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Private Method ZCL_ALV_POPUP->ASSIGN_ALV_DATA
* +-------------------------------------------------------------------------------------------------+
* | [--->] IT_DATA TYPE TABLE
* | [<---] ER_DATA TYPE REF TO DATA
* | [<---] ER_TABLE_TYPE TYPE REF TO CL_ABAP_TABLEDESCR
* +--------------------------------------------------------------------------------------</SIGNATURE>
METHOD assign_alv_data.
DATA:
lr_tdata TYPE REF TO data,
lr_sdata TYPE REF TO data,
lr_type TYPE REF TO cl_abap_typedescr,
lr_table TYPE REF TO cl_abap_tabledescr,
lr_struct TYPE REF TO cl_abap_structdescr,
lt_field TYPE cl_abap_structdescr=>component_table,
lt_final TYPE cl_abap_structdescr=>component_table,
ls_final TYPE LINE OF cl_abap_structdescr=>component_table.
FIELD-SYMBOLS: <fs> TYPE any,
<fs_t_data> TYPE STANDARD TABLE,
<fs_s_data> TYPE any.
CLEAR: er_data, er_table_type.
ASSIGN it_data TO <fs>.
GET REFERENCE OF <fs> INTO lr_tdata.
cl_abap_tabledescr=>describe_by_data_ref(
EXPORTING
p_data_ref = lr_tdata
RECEIVING
p_descr_ref = lr_type
EXCEPTIONS
reference_is_initial = 1
OTHERS = 2
).
IF sy-subrc <> 0.
MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
ENDIF.
er_table_type ?= lr_type.
CHECK er_table_type IS BOUND.
lr_struct ?= er_table_type->get_table_line_type( ).
CHECK lr_struct IS BOUND.
lt_field = lr_struct->get_components( ).
CLEAR: ls_final, lr_struct, lr_table.
ls_final-name = 'CHOOSE'.
ls_final-type ?= cl_abap_datadescr=>describe_by_name( 'XFELD' ).
APPEND ls_final TO lt_final.
APPEND LINES OF lt_field TO lt_final.
lr_struct = cl_abap_structdescr=>create( lt_final ).
lr_table = cl_abap_tabledescr=>create( lr_struct ).
CREATE DATA me->mr_alv_data TYPE HANDLE lr_table.
CREATE DATA lr_sdata TYPE HANDLE lr_struct.
ASSIGN me->mr_alv_data->* TO <fs_t_data>.
ASSIGN lr_sdata->* TO <fs_s_data>.
LOOP AT it_data ASSIGNING <fs>.
CLEAR <fs_s_data>.
MOVE-CORRESPONDING <fs> TO <fs_s_data>.
APPEND <fs_s_data> TO <fs_t_data>.
ENDLOOP.
GET REFERENCE OF <fs_t_data> INTO er_data.
ENDMETHOD. "ASSIGN_ALV_DATA
* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Public Method ZCL_ALV_POPUP->CONSTRUCTOR
* +-------------------------------------------------------------------------------------------------+
* | [--->] IT_DATA TYPE TABLE
* | [--->] IV_PROG_NAME TYPE SYREPID(optional)
* | [--->] IV_PF_STATUS TYPE SYPFKEY(optional)
* | [--->] IV_MULTI_SELECT TYPE ABAP_BOOL(optional)
* +--------------------------------------------------------------------------------------</SIGNATURE>
METHOD constructor.
CLEAR: me->mr_alv,
me->mr_alv_data,
me->mr_table_type,
me->mv_pf_status,
me->mv_prog_name,
me->mv_multi_select.
me->mv_pf_status = iv_pf_status.
me->mv_prog_name = iv_prog_name.
me->mv_multi_select = iv_multi_select.
me->assign_alv_data(
EXPORTING
it_data = it_data
IMPORTING
er_data = me->mr_alv_data
er_table_type = me->mr_table_type
).
ENDMETHOD. "constructor
* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Public Method ZCL_ALV_POPUP->DISPLAY
* +-------------------------------------------------------------------------------------------------+
* | [--->] IV_START_COLUMN TYPE I
* | [--->] IV_START_LINE TYPE I
* | [--->] IV_END_COLUMN TYPE I(optional)
* | [--->] IV_END_LINE TYPE I(optional)
* +--------------------------------------------------------------------------------------</SIGNATURE>
METHOD display.
DATA:
lr_functions TYPE REF TO cl_salv_functions_list,
lr_columns TYPE REF TO cl_salv_columns,
lr_column TYPE REF TO cl_salv_column_table,
lr_selections TYPE REF TO cl_salv_selections,
lr_events TYPE REF TO cl_salv_events_table.
FIELD-SYMBOLS <fs_t_data> TYPE STANDARD TABLE.
ASSIGN me->mr_alv_data->* TO <fs_t_data>.
TRY.
cl_salv_table=>factory(
IMPORTING
r_salv_table = me->mr_alv
CHANGING
t_table = <fs_t_data> ).
CATCH cx_salv_msg. "#EC NO_HANDLER
ENDTRY.
lr_functions = me->mr_alv->get_functions( ).
lr_functions->set_all( if_salv_c_bool_sap=>true ).
lr_columns = me->mr_alv->get_columns( ).
lr_columns->set_optimize( if_salv_c_bool_sap=>true ).
TRY.
lr_column ?= lr_columns->get_column( 'CHOOSE' ).
lr_column->set_cell_type( if_salv_c_cell_type=>checkbox_hotspot ).
lr_column->set_short_text( 'Choose'(t01) ).
lr_column->set_medium_text( 'Choose'(t01) ).
lr_column->set_long_text( 'Choose'(t01) ).
CATCH cx_salv_not_found. "#EC NO_HANDLER
ENDTRY.
lr_selections = me->mr_alv->get_selections( ).
lr_selections->set_selection_mode( if_salv_c_selection_mode=>none ).
IF me->mv_pf_status IS NOT INITIAL AND me->mv_prog_name IS NOT INITIAL.
me->mr_alv->set_screen_status(
pfstatus = me->mv_pf_status
report = me->mv_prog_name
set_functions = me->mr_alv->c_functions_all ).
ENDIF.
lr_events = me->mr_alv->get_event( ).
SET HANDLER me->on_user_command FOR lr_events.
SET HANDLER me->on_link_click FOR lr_events.
me->mr_alv->set_screen_popup(
start_column = iv_start_column
end_column = iv_end_column
start_line = iv_start_line
end_line = iv_end_line ).
me->mr_alv->display( ).
ENDMETHOD. "display_popup
* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Static Public Method ZCL_ALV_POPUP=>FACTORY
* +-------------------------------------------------------------------------------------------------+
* | [--->] IT_DATA TYPE TABLE
* | [--->] IV_PROG_NAME TYPE SYREPID(optional)
* | [--->] IV_PF_STATUS TYPE SYPFKEY(optional)
* | [--->] IV_MULTI_SELECT TYPE ABAP_BOOL (default =ABAP_TRUE)
* | [<-()] R_ALV_POPUP TYPE REF TO ZCL_ALV_POPUP
* +--------------------------------------------------------------------------------------</SIGNATURE>
METHOD factory.
CLEAR r_alv_popup.
CREATE OBJECT r_alv_popup
EXPORTING
it_data = it_data
iv_prog_name = iv_prog_name
iv_pf_status = iv_pf_status
iv_multi_select = iv_multi_select.
ENDMETHOD. "factory
* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Private Method ZCL_ALV_POPUP->GET_SELECTED_DATA
* +-------------------------------------------------------------------------------------------------+
* | [<---] ET_DATA TYPE TABLE
* +--------------------------------------------------------------------------------------</SIGNATURE>
METHOD get_selected_data.
DATA: lr_t_data TYPE REF TO data,
lr_s_data TYPE REF TO data,
lr_struct TYPE REF TO cl_abap_structdescr,
lv_cnt TYPE i.
FIELD-SYMBOLS: <fs_t_tdata> TYPE STANDARD TABLE,
<fs_s_tdata> TYPE any,
<fs_t_fdata> TYPE STANDARD TABLE,
<fs_s_fdata> TYPE any,
<fs> TYPE any,
<fs_tdata> TYPE any,
<fs_fdata> TYPE any.
CLEAR et_data.
lr_struct ?= me->mr_table_type->get_table_line_type( ).
CHECK lr_struct IS BOUND.
CREATE DATA lr_t_data TYPE HANDLE me->mr_table_type.
CREATE DATA lr_s_data TYPE HANDLE lr_struct.
ASSIGN lr_t_data->* TO <fs_t_fdata>.
ASSIGN lr_s_data->* TO <fs_s_fdata>.
ASSIGN me->mr_alv_data->* TO <fs_t_tdata>.
LOOP AT <fs_t_tdata> ASSIGNING <fs_s_tdata>.
IF <fs_s_tdata> IS ASSIGNED.
ASSIGN COMPONENT 'CHOOSE' OF STRUCTURE <fs_s_tdata> TO <fs> CASTING TYPE xfeld.
IF <fs> IS ASSIGNED.
IF <fs> = abap_true.
CLEAR <fs_s_fdata>.
DO.
lv_cnt = sy-index + 1.
ASSIGN COMPONENT lv_cnt OF STRUCTURE <fs_s_tdata> TO <fs_tdata>.
IF sy-subrc <> 0.
EXIT.
ENDIF.
ASSIGN COMPONENT sy-index OF STRUCTURE <fs_s_fdata> TO <fs_fdata>.
IF <fs_tdata> IS ASSIGNED AND <fs_fdata> IS ASSIGNED.
<fs_fdata> = <fs_tdata>.
ENDIF.
ENDDO.
APPEND <fs_s_fdata> TO <fs_t_fdata>.
ENDIF.
ENDIF.
ENDIF.
ENDLOOP.
et_data = <fs_t_fdata>.
ENDMETHOD. "GET_SELECTED_DATA
* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Private Method ZCL_ALV_POPUP->ON_LINK_CLICK
* +-------------------------------------------------------------------------------------------------+
* | [--->] ROW LIKE
* | [--->] COLUMN LIKE
* +--------------------------------------------------------------------------------------</SIGNATURE>
METHOD on_link_click.
FIELD-SYMBOLS: <fs_t_data> TYPE STANDARD TABLE,
<fs_s_data> TYPE any,
<fs> TYPE any.
CHECK mr_alv IS BOUND.
ASSIGN me->mr_alv_data->* TO <fs_t_data>.
READ TABLE <fs_t_data> ASSIGNING <fs_s_data> INDEX row.
IF <fs_s_data> IS ASSIGNED.
ASSIGN COMPONENT 'CHOOSE' OF STRUCTURE <fs_s_data> TO <fs> CASTING TYPE xfeld.
IF <fs> IS ASSIGNED.
IF <fs> = abap_false.
<fs> = abap_true.
ELSE.
<fs> = abap_false.
ENDIF.
ENDIF.
ENDIF.
IF mv_multi_select = abap_false.
LOOP AT <fs_t_data> ASSIGNING <fs_s_data>.
IF <fs_s_data> IS ASSIGNED AND sy-tabix <> row.
ASSIGN COMPONENT 'CHOOSE' OF STRUCTURE <fs_s_data> TO <fs> CASTING TYPE xfeld.
IF <fs> IS ASSIGNED.
<fs> = abap_false.
ENDIF.
ENDIF.
ENDLOOP.
ENDIF.
mr_alv->refresh( ).
ENDMETHOD. "on_link_click
* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Private Method ZCL_ALV_POPUP->ON_USER_COMMAND
* +-------------------------------------------------------------------------------------------------+
* | [--->] E_SALV_FUNCTION LIKE
* +--------------------------------------------------------------------------------------</SIGNATURE>
METHOD on_user_command.
DATA lr_data TYPE REF TO data.
FIELD-SYMBOLS <fs_data> TYPE STANDARD TABLE.
CASE e_salv_function.
WHEN mc_func_refresh OR mc_func_deselectall.
me->select_all( iv_value = abap_false ).
WHEN mc_func_selectall.
me->select_all( iv_value = abap_true ).
WHEN OTHERS.
CREATE DATA lr_data TYPE HANDLE me->mr_table_type.
ASSIGN lr_data->* TO <fs_data>.
me->get_selected_data(
IMPORTING
et_data = <fs_data>
).
RAISE EVENT button_click
EXPORTING
ev_salv_function = e_salv_function
et_selected_data = <fs_data>.
ENDCASE.
ENDMETHOD. "on_user_command
* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Private Method ZCL_ALV_POPUP->SELECT_ALL
* +-------------------------------------------------------------------------------------------------+
* | [--->] IV_VALUE TYPE ABAP_BOOL (default =ABAP_TRUE)
* +--------------------------------------------------------------------------------------</SIGNATURE>
METHOD select_all.
FIELD-SYMBOLS: <fs_t_data> TYPE STANDARD TABLE,
<fs_s_data> TYPE any,
<fs> TYPE any.
CHECK mr_alv IS BOUND.
ASSIGN me->mr_alv_data->* TO <fs_t_data>.
LOOP AT <fs_t_data> ASSIGNING <fs_s_data>.
IF <fs_s_data> IS ASSIGNED.
ASSIGN COMPONENT 'CHOOSE' OF STRUCTURE <fs_s_data> TO <fs> CASTING TYPE xfeld.
IF <fs> IS ASSIGNED.
<fs> = iv_value.
ENDIF.
ENDIF.
ENDLOOP.
mr_alv->refresh( ).
ENDMETHOD. "select_all
ENDCLASS.