In this article I’ll present an approach how to handle a screen with a global ABAP class. The idea is simple – we will create a class which will listen to PAI and PBO events raised by the screen. All data processing and screen element manipulation is done in the class code. Let’s check out how exactly it is done
In SE80 create a function group with one function module and one screen. The function module will be the entry point from the class. The screen will be used to draw elements on the screen. The screen elements will be manipulated from the ABAP class code.
For demonstration purposes we will have only a screen with one grid and we will capture just the OKCODE. So we will have one global variable defined in TOP include:
FUNCTION-POOL ZCA_ALV.
DATA:
g_okcode TYPE okcode.
The code of our new function module will also be simple:
FUNCTION ZCA_ALV_GRID1.
* call the editor screen
call screen 100.
ENDFUNCTION.
Now we create the screen 0100.
Please note the size of the screen – this is because we would like the ALV grid to be stretched across the whole page and we don’t want double scroll bars (issue when grid is too large) – this will require also modification in the screen layout (explained later).
In the following picture you can see how the global variable G_OKCODE is connected to the screen (is passed in/from the screen)
The flow logic of our new screen is trivial:
PROCESS BEFORE OUTPUT.
MODULE pbo.
*
PROCESS AFTER INPUT.
MODULE pai.
In new include for modules PBO and PAI we put the following simple code
*&---------------------------------------------------------------*
*& Module PBO OUTPUT
*&---------------------------------------------------------------*
* text
*----------------------------------------------------------------*
MODULE pbo OUTPUT.
DATA:
lt_ucomm TYPE TABLE OF sy-ucomm.
FIELD-SYMBOLS:
<fs_ucomm> type sy-ucomm.
* This will ensure some commands/buttons will by hidden/disabled
CLEAR lt_ucomm[].
APPEND INITIAL LINE TO lt_ucomm ASSIGNING <fs_ucomm>.
<fs_ucomm> = 'EXECUTE'.
SET PF-STATUS 'MY_PF_STATUS' excluding lt_ucomm.
SET TITLEBAR 'MY_TITLEBAR'.
zcl_ca_grid_handling=>raise_pbo( i_dynnr = sy-dynnr ).
ENDMODULE. " PBO OUTPUT
*&---------------------------------------------------------------*
*& Module PAI INPUT
*&---------------------------------------------------------------*
* text
*----------------------------------------------------------------*
MODULE pai INPUT.
IF g_okcode = 'CANC'.
SET SCREEN 0.
ENDIF.
zcl_ca_grid_handling=>raise_pai(
i_dynnr = sy-dynnr
i_okcode = g_okcode
).
ENDMODULE. " PAI INPUT
Now in the layout editor for screen 0100 I’ll create the ALV grid container. Again please note – the grid size is the same as screen size (-1 so it fits in) and what is also important – note the Resize section – this will ensure the grid will not have it’s own scrollbar (no double scroll bars)
Now let’s step forward to the class (Usual ABAP class) creation. In screen 0100 we are calling two static methods – RAISE_PAI and RAISE_PBO. We have to define the corresponding interface
Their code is simple:
METHOD raise_pai.
RAISE EVENT pai
EXPORTING
i_dynnr = i_dynnr
i_okcode = i_okcode.
ENDMETHOD.
METHOD raise_pbo.
RAISE EVENT pbo
EXPORTING i_dynnr = i_dynnr.
ENDMETHOD.
You can see we’re raising some non-standard events – so we have to define them with the corresponding interface:
If we want to react on an event, we have to register a listener for it and have a method to handle it. The listener registration can be put directly in the class instance constructor:
METHOD constructor.
* register for the events
SET HANDLER handle_pai.
SET HANDLER handle_pbo.
ENDMETHOD.
We have registered listener methods (HANDLE_PAI, HANDLE_PBO) but we actually don’t have them implemented yet so let’s create them now:
Now we would like to implement our handlers. At first we have to define their interface – this is easy as class designer offers a button to fill the parameters automatically according to the event:
Finally we can fill our event handlers with some code:
METHOD handle_pbo.
CASE i_dynnr.
WHEN '0100'.
show_editor( ).
* WHEN OTHERS.
ENDCASE.
ENDMETHOD.
METHOD HANDLE_PAI.
CASE i_dynnr.
WHEN '0100'.
"screen 0100: configuration
CASE i_okcode.
WHEN 'CANCEL' OR 'LEAVE' OR 'BACK'.
SET SCREEN 0.
* WHEN OTHERS.
ENDCASE.
ENDCASE.
ENDMETHOD.
Method SHOW_EDITOR in HANDLE_PBO is a method for creation of the container object, ALV grid object and displaying it.
It uses standard ALV components CL_GUI_CUSTOM_CONTAINER and CL_GUI_ALV_GRID and displays data of SFLIGHT – we will keep the data and references to container and grid in class attributes:
The simplest form of the SHOW_EDITOR method might look like this:
METHOD show_editor.
DATA:
lt_fieldcat TYPE lvc_t_fcat,
ls_layout TYPE lvc_s_layo,
ls_variant TYPE disvariant.
IF me->mr_container IS INITIAL.
CREATE OBJECT me->mr_container
EXPORTING
container_name = 'GO_GRID_CONTAINER'.
CREATE OBJECT me->mr_grid
EXPORTING
i_parent = me->mr_container.
ls_layout-sel_mode = 'A'.
ls_layout-no_rowmark = abap_true.
ls_layout-cwidth_opt = abap_true.
ls_variant-report = sy-repid.
ls_variant-username = sy-uname.
CALL FUNCTION 'LVC_FIELDCATALOG_MERGE'
EXPORTING
i_structure_name = 'SFLIGHT'
CHANGING
ct_fieldcat = lt_fieldcat.
SELECT * INTO TABLE mt_data FROM sflight.
me->mr_grid->set_table_for_first_display(
EXPORTING
is_layout = ls_layout
is_variant = ls_variant
i_save = 'A'
i_default = 'X'
CHANGING
it_fieldcatalog = lt_fieldcat
it_outtab = mt_data ).
ENDIF.
ENDMETHOD.
Now we have everything prepared…so we just add one more public class method to run the whole magic 🙂
The code is simple:
METHOD run.
CALL FUNCTION 'ZCA_ALV_GRID1'.
ENDMETHOD.
Here’s the output after ZCL_CA_GRID_HANDLING is instantiated and method RUN is called:
Let’s put a breakpoint on first line of method HANDLE_PAI to make sure the method is called when user performs an action in the screen (I pressed ESC…OK_CODE=’BACK’):
Voila ! We have fully functional ALV handled by an ABAP global class.
Thank you, this info was very helpfull.
Hi,
Good article, thanks. Say if you wanted to process all the fields on the screen – for example, save all the field values into a database table. Would you need to pass all the values via the raise_PAI event?
Hi JFG,
I didn’t think of this much yet (having a dynpro with fields already defined using Layout designed) and didn’t try yet – but now I will 🙂
Code in this article was used just to manage one ALV grid by a global class.
But I believe there’s a was how to access screen components dynamically so it should also be possible to access them from the global class without a need to pass their values back and forth from/to the dynpro. I’ll check it out and let you know if it’s possible (in another article) or I’ll leave a comment here if this is not possible/not practical.