In a world of Web Dynpro and cool UI5 libraries, I still find myself working with ABAP Reports and classic Dynpros. Being a techie, it is easy to imagine why I don't see these kinds of tasks very intriguing. Yet I wish to make it interesting by exploring modern (and better) ways to improve development.
So... This is a short guide on how to implement an ABAP report using the BUS-Screen Framework. Although this was initially intended for internal SAP usage only, it is not publicly available.
Misconception
If you search online on how to use BUS-Screen Framework, besides not getting a lot of results, you will also get some wrongful information. BUS-Screen Framework cannot dynamically create Dynpros. It is merely a way to structure reports in an object-oriented way.
Still interested? ... Great!
First and foremost, I have to recommend the book Anwendungsentwicklung mit ABAP Objects by Thorsten Franz and Tobias Trapp, which contains a whole subchapter dedicated to the BUS-Screen Framework.
All SAP objects related to this framework can be found in package BUS_TOOLS. This package also contains a small demo transaction, but I think it's a little unclear.
![bus_tools.png]()
The following steps describe the basis for a screen implementation using BUS-Screen Framework:
- Create a new report with a normal screen. (I've named my screen '2000').
In the Flow Logic of Screen 2000, call modules dynpro_pbo for output, respectively dynpro_pai for input.
PROCESS BEFORE OUTPUT. MODULE dynpro_pbo.
PROCESS AFTER INPUT. MODULE dynpro_pai.
- Declare these two modules either directly in the report or inside an include.
MODULE dynpro_pbo OUTPUT. cl_bus_abstract_screen=>dynpro_pbo( iv_dynpro_number = sy-dynnr iv_program_name = sy-repid ).
ENDMODULE.
MODULE dynpro_pai INPUT. cl_bus_abstract_screen=>dynpro_pai( iv_dynpro_number = sy-dynnr iv_program_name = sy-repid ).
ENDMODULE.
NOTE: These modules must only be declared once and then reused for every screen (both normal and sub screens).
- One of the conditions for instantiating screens using this framework is to declare a form routine inside the program.
FORM bus_screen_create USING value(im_program_name) TYPE bus_screen-program_name value(im_dynpro_number) TYPE bus_screen-dynpro_number CHANGING ch_screen ##called. CASE im_dynpro_number. WHEN '2000'.
" This is the name of the wrapper class for Screen 2000
" If the called iv_dynpro_number is not found and the ch_screen is not instantiated,
" a dummy screen of type CL_BUS_ABSTRACT_SCREEN will be return. CREATE OBJECT ch_screen TYPE lcl_demo_main_screen EXPORTING iv_program_name = im_program_name iv_dynpro_number = im_dynpro_number. ENDCASE.
ENDFORM.
- Now it's time to define the screen logic in an object-oriented way using a local ABAP class.
NOTE: Although class CL_BUS_ABSTRACT_SCREEN is the base, it is important to implement the correct inheritance. In this case, CL_BUS_ABSTRACT_MAIN_SCREEN must be used since 2000 is a normal screen. (For sub screens, the corresponding CL_BUS_ABSTRACT_SUB_SCREEN should be used)
CLASS lcl_demo_main_screen DEFINITION INHERITING FROM cl_bus_abstract_main_screen FINAL. PUBLIC SECTION.
" The constructor method can be used for initializations. METHODS constructor IMPORTING value(iv_program_name) TYPE bus_screen-program_name value(iv_dynpro_number) TYPE bus_screen-dynpro_number. PROTECTED SECTION.
" The following two methods must be redefined as ABAP Objects
" does not support the CALL SCREEN statement. METHODS call_screen REDEFINITION. METHODS call_screen_starting_at REDEFINITION. PRIVATE SECTION.
" This method is the central handling for all PAI events in this screen. METHODS handle_pai FOR EVENT process_after_input OF cl_bus_abstract_main_screen IMPORTING iv_function_code.
ENDCLASS.
CLASS lcl_demo_main_screen IMPLEMENTATION. METHOD constructor. super->constructor( EXPORTING iv_program_name = iv_program_name iv_dynpro_number = iv_dynpro_number ).
" The GUI Title of the application is set using the following method set_title( 'DEMO BUS-Screen Framework' ). SET HANDLER handle_pai FOR me. ENDMETHOD. METHOD call_screen. CALL SCREEN iv_dynpro_number. ENDMETHOD. METHOD call_screen_starting_at. CALL SCREEN iv_dynpro_number STARTING AT iv_xstart iv_ystart ENDING AT iv_xend iv_yend. ENDMETHOD. METHOD handle_pai. CASE iv_function_code.
" For the default GUI Status, global constants can be used to evaluate the function code.
" However, if you set your own GUI Status using method set_status( ),
" then you will have to evaluate your specific function codes. WHEN gc_function_code_back OR gc_function_code_exit. leave( ). WHEN gc_function_code_cancel. LEAVE PROGRAM. ENDCASE. ENDMETHOD.
ENDCLASS.
- Now that our screen is defined, we can call it. For this, the following code should be used in the START-OF-SELECTION event:
DATA lo_main_screen TYPE REF TO lcl_demo_main_screen.
" This statement will try to call the BUS_SCREEN_CREATE form routine that we previously defined.
cl_bus_abstract_screen=>get_screen( EXPORTING iv_program_name = sy-repid iv_dynpro_number = '2000' IMPORTING ev_screen = lo_main_screen ).
IF lo_main_screen IS BOUND. lo_main_screen->show( ).
ENDIF.
This pretty much sums up the basic functionality. In the next blogs, I will show you how to use the tabstrip wrapper (CL_BUS_TABSTRIP and CL_BUS_TABSTRIP_TAB classes) and also how to handle messages (CL_BUS_MESSAGE).