I want to use an ALV grid with a selection screen but without adding additional dynpros and PAI PBO Modules, like shown in this Example.
Everything works fine, but I can't go back from ALV to selection screen since the report gets terminated.
For my understanding,
I need to adapt this part of code.
If I don't call the function RS_SET_SELSCREEN_STATUS
,
I can go back to selection screen, but the F8
button is showing during the ALV Screen.
* Drucktastenleiste: Button "Ausführen (F8)" entfernen
DATA: it_exclude_btn TYPE STANDARD TABLE OF rsexfcode WITH DEFAULT KEY.
it_exclude_btn = VALUE #( ( fcode = 'ONLI' ) ).
CALL FUNCTION 'RS_SET_SELSCREEN_STATUS'
EXPORTING
p_status = '%_00' " akt. Standard-PF-Status des Dypro 2000
TABLES
p_exclude = it_exclude_btn.
* leere SAP-Toolbar ausblenden
cl_abap_list_layout=>suppress_toolbar( ).
* Focus auf ALV setzen
cl_gui_alv_grid=>set_focus( control = o_alv ).
* Flag für Screen-Status auf ALV-Anzeige setzen
gv_screen_status = 'IN_ALV'.
ENDIF.
Please help me to make the Back Button work in ALV view.
EDIT:
You can test the behaviour using the code below:
**********************************************************************
*
* Variablen
*
**********************************************************************
DATA: gv_screen_status TYPE string VALUE 'INIT'.
DATA: gv_carrid TYPE spfli-carrid.
DATA: gv_connid TYPE spfli-connid.
DATA: o_alv TYPE REF TO cl_gui_alv_grid.
DATA: it_spfli TYPE STANDARD TABLE OF spfli WITH DEFAULT KEY.
**********************************************************************
*
* leeres Dynpro als Dummy für ALV-Grid
*
**********************************************************************
SELECTION-SCREEN BEGIN OF SCREEN 2000.
SELECTION-SCREEN END OF SCREEN 2000.
**********************************************************************
*
* SELECTION-SCREEN
*
**********************************************************************
SELECT-OPTIONS: so_carr FOR gv_carrid.
SELECT-OPTIONS: so_conn FOR gv_connid.
**********************************************************************
*
* Eventhandler
*
**********************************************************************
CLASS lcl_events DEFINITION.
PUBLIC SECTION.
CLASS-METHODS:
on_toolbar FOR EVENT toolbar OF cl_gui_alv_grid
IMPORTING
e_object
e_interactive
sender.
CLASS-METHODS:
on_user_command FOR EVENT user_command OF cl_gui_alv_grid
IMPORTING
e_ucomm
sender.
CLASS-METHODS:
on_data_changed FOR EVENT data_changed OF cl_gui_alv_grid
IMPORTING
er_data_changed
sender.
ENDCLASS.
CLASS lcl_events IMPLEMENTATION.
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_spfli rausholen und daraus die Zelle anhand des Spaltennamens (Feldnamens) holen
ASSIGN COMPONENT <c>-fieldname OF STRUCTURE it_spfli[ <c>-row_id ] TO FIELD-SYMBOL(<f>).
IF <f> IS ASSIGNED.
* Änderungswert in die Zelle der iTab (it_spfli) rückschreiben
<f> = <c>-value.
ENDIF.
ENDIF.
ENDLOOP.
* DB Update
FIELD-SYMBOLS: <tab> TYPE table.
FIELD-SYMBOLS: <row> TYPE spfli.
ASSIGN er_data_changed->mp_mod_rows->* TO <tab>.
LOOP AT <tab> ASSIGNING <row>.
* DB Update hier
ENDLOOP.
ENDMETHOD.
METHOD on_user_command.
* wenn BTN_REFRESH geklickt
IF e_ucomm = 'BTN_REFRESH'.
IF o_alv IS BOUND.
SELECT * FROM spfli INTO TABLE @it_spfli
WHERE carrid IN @so_carr
AND connid IN @so_conn.
sender->refresh_table_display( is_stable = VALUE lvc_s_stbl( row = abap_true
col = abap_true )
i_soft_refresh = abap_false ).
ENDIF.
ENDIF.
ENDMETHOD.
METHOD on_toolbar.
* alle Buttons entfernen, bis auf folgende:
DELETE e_object->mt_toolbar WHERE
function NE cl_gui_alv_grid=>mc_fc_refresh " Refresh
AND function NE cl_gui_alv_grid=>mc_mb_export " Excel
AND function NE cl_gui_alv_grid=>mc_fc_current_variant. " Layout
LOOP AT e_object->mt_toolbar ASSIGNING FIELD-SYMBOL(<fs_button>) WHERE ( function = cl_gui_alv_grid=>mc_fc_refresh ).
* neues USER-Command setzen, damit bei Button-Klick on_user_command getriggert wird
<fs_button>-function = 'BTN_REFRESH'.
ENDLOOP.
ENDMETHOD.
ENDCLASS.
**********************************************************************
*
* INITIALIZATION
*
**********************************************************************
INITIALIZATION.
* Vorbelegungen für Selektionsbild
so_carr[] = VALUE #( ( sign = 'I' option = 'EQ' low = 'LH' ) ).
**********************************************************************
*
* AT SELECTION-SCREEN OUTPUT
*
**********************************************************************
AT SELECTION-SCREEN OUTPUT.
* Wenn vorher das Selektionsbild 1000 angezeigt wurde
IF gv_screen_status = 'IN_SELECTION'.
* Daten holen
SELECT * FROM spfli INTO TABLE @it_spfli
WHERE carrid IN @so_carr
AND connid IN @so_conn.
* ALV-Gitter anzeigen
o_alv = NEW #( 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.
* Ereignisse registrieren
o_alv->register_edit_event( i_event_id = cl_gui_alv_grid=>mc_evt_enter ).
o_alv->register_edit_event( i_event_id = cl_gui_alv_grid=>mc_evt_modified ).
* ALV-Grid selektionsbereit setzen
o_alv->set_ready_for_input( i_ready_for_input = 1 ).
* Layout des ALV setzen
DATA(lv_layout) = VALUE lvc_s_layo( zebra = abap_true
cwidth_opt = 'A'
grid_title = 'Flugverbindungen' ).
* Feldkatalog automatisch durch SALV erstellen lassen
DATA: o_salv TYPE REF TO cl_salv_table.
cl_salv_table=>factory( IMPORTING
r_salv_table = o_salv
CHANGING
t_table = it_spfli ).
DATA(it_fcat) = cl_salv_controller_metadata=>get_lvc_fieldcatalog( r_columns = o_salv->get_columns( )
r_aggregations = o_salv->get_aggregations( ) ).
* im Feldkatalog alle Zellen der Spalte "CITYFROM" des ALV-Grids auf
* editierbar stellen, die restlichen Zellen sind nicht editierbar
LOOP AT it_fcat ASSIGNING FIELD-SYMBOL(<fcat>).
CASE <fcat>-fieldname.
WHEN 'CITYFROM'.
<fcat>-edit = abap_true.
WHEN OTHERS.
<fcat>-edit = abap_false.
ENDCASE.
ENDLOOP.
* ALV anzeigen
o_alv->set_table_for_first_display( EXPORTING
i_bypassing_buffer = abap_false
i_save = 'A'
is_layout = lv_layout
CHANGING
it_fieldcatalog = it_fcat
it_outtab = it_spfli ).
* Drucktastenleiste: Button "Ausführen (F8)" entfernen
DATA: it_exclude_btn TYPE STANDARD TABLE OF rsexfcode WITH DEFAULT KEY.
it_exclude_btn = VALUE #( ( fcode = 'ONLI' ) ).
CALL FUNCTION 'RS_SET_SELSCREEN_STATUS'
EXPORTING
p_status = '%_00' " akt. Standard-PF-Status des Dypro 2000
TABLES
p_exclude = it_exclude_btn.
* leere SAP-Toolbar ausblenden
cl_abap_list_layout=>suppress_toolbar( ).
* Focus auf ALV setzen
cl_gui_alv_grid=>set_focus( control = o_alv ).
* Flag für Screen-Status auf ALV-Anzeige setzen
gv_screen_status = 'IN_ALV'.
ENDIF.
**********************************************************************
*
* START-OF-SELECTION
*
**********************************************************************
START-OF-SELECTION.
* Wir befinden uns im Anzeigebereich des Selektionsbildes
gv_screen_status = 'IN_SELECTION'.
* Trick: leeren Dummy-Screen 2000 anzeigen und intern für das ALV-Grid in
* AT SELECTION-SCREEN OUTPUT als cl_gui_container=>default_screen nutzen
CALL SELECTION-SCREEN 2000.
Best Answer
The reason why leaving the Selection Screen
2000
doesn't make your return to the previous default Selection Screen (1000
) is that you have assigned the incorrect GUI Status%_00
(of the Kernel programRSSYSTDB
) to the screen2000
, which is the standard one assigned to the default Selection Screen (1000
). Hence, the ABAP kernel thinks that Back is pressed on the main Selection Screen and exits the program.More specifically, it's the value of the Function Code which is tested by the kernel: in the GUI Status
%_00
, the Back button corresponds to the function codeE
, so if you create a custom GUI Status with a button assigned to the function codeE
, pressing this button will also leave the program.Solution: for a selection screen called with
CALL SELECTION-SCREEN
, the default standard GUI Status%_CS
is used, so your custom GUI Status should use its Function Codes (CBAC
for the Back button), and the default Selection Screen1000
will then be displayed (in debug, you will see that the ABAP statement afterCALL SELECTION-SCREEN 2000
is executed, which was not the case with%_00
, and so it will return to the main Selection Screen).So, one solution is the below one (Edit: adding
CRET
to excludeF8
), but you may choose other solutions now that you understand what the original issue was.As one can see,
F8
is assigned toCRET
in the GUI Status%_CS
ofRSSYSTDB
:The issue is not related to ALV, it's a pure selection screen issue. Here is the minimal code to reproduce the issue (the code doesn't continue after
CALL SELECTION-SCREEN 2000
after Back has been pressed):For information, here are the GUI statuses and their main buttons/function codes, depending on the exact context how the selection screen is called (see table legend (*)):
... (full screen)
... AS WINDOW (popup)
... (before job is created)
%_00
%_CS
%_CSP
%_JB
(*) Legend: "(E)" if a function is of type Exit, i.e. triggers
AT SELECTION-SCREEN ON EXIT-COMMAND
(others triggerAT SELECTION-SCREEN
), "" means that pressing Enter corresponds to an empty function code, "N/A" means that the function is not available.(**) Either SUBMIT without extension, or default selection screen 1000 exists and is shown, or SUBMIT ... USING SELECTION-SCREEN <number> ..., or Transaction Code calling an Executable Program (type 1)
Note that in Selection Screens, if needed to test the function code, the field
sscrfields-ucomm
should be used as shown in the example below (NB: in Dynpro programming,SY-UCOMM
is always to be avoided; complete path: Home > ABAP_PLATFORM_NEW > Classic Screen Programming > General Dynpros > Processing Screens > User Actions on Screens > Reading Function Code):