Application Development Blog Posts
Learn and share on deeper, cross technology development topics such as integration and connectivity, automation, cloud extensibility, developing at scale, and security.
cancel
Showing results for 
Search instead for 
Did you mean: 
TudorRiscutia
Active Participant

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.

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

2 Comments