Additional Blogs by Members
cancel
Showing results for 
Search instead for 
Did you mean: 
FabioPagoti
Active Contributor

Believe it or not, I still hear many complains from ABAP Objects developers wannabes about the lack of good object oriented program examples. Here comes another one.

Background

I have been working on a 100% custom solution for the past months which was increasing in size an complexity very fast. At the moment we reached 5 Z-transaction codes, I decided that it was a good time to help the user not to have to remember all transaction codes by heart. So, I decided to create a very simple dashboard (or cockpit if you will) from an executable program which would enable the user to have to remember just one transaction code - the dashboard itself.

By the way, this solution is still under development and there are more than 15 transaction codes including programs, interfaces, configuration tables etc.

Before start

As we are in the 21 century, let's forget the idea of creating a new program as below.

Report z_solution_dashboard.

" Selection screen

" ...

" Black hole of global variables

" ...

START-OF-SELECTION.

perform f_do_everything.

Dashboard UI

First, let's take a look on how the dashboard look like.

I spitted the selection screen into different sections. In this demo, the division was done according to the type of SAP object to be called. In the real scenario I decided to keep the most often used transactions in the upper part and hardly ever used configuration stuff way down the screen.

Basically the selection screen is creating using a set of pieces of code as the one below:

* Programs

SELECTION-SCREEN BEGIN OF BLOCK b_reports WITH FRAME TITLE text-b00 NO INTERVALS.

SELECTION-SCREEN SKIP 1.

SELECTION-SCREEN BEGIN OF LINE.

SELECTION-SCREEN PUSHBUTTON 10(30) pb_prg1 USER-COMMAND sppfdemo.         " Program Name / Transaction

SELECTION-SCREEN PUSHBUTTON 45(30) pb_prg1i USER-COMMAND sapmppfbookdemo. " Program Documentation

SELECTION-SCREEN END OF LINE.

SELECTION-SCREEN SKIP 1.

SELECTION-SCREEN BEGIN OF LINE.

SELECTION-SCREEN PUSHBUTTON 10(30) pb_prg2 USER-COMMAND z_sol_1.          " Your Z## program

SELECTION-SCREEN PUSHBUTTON 45(30) pb_prg2i USER-COMMAND z_sol_prog_1.    " Your Z## program documentation

SELECTION-SCREEN END OF LINE.

SELECTION-SCREEN SKIP 1.

SELECTION-SCREEN END OF BLOCK b_reports.

Pay attention in the addition USER-COMMAND. I intentionally set its content to be the name of the SAP object to be called. In the example above, when pb_prg1 is pressed, transaction code sppfdemo will be called. On the other hand, when pb_prg1i  (note the 'i' at the end) is pressed, the documentation of program sapmppfbookdemo will be called.

Dashboard Model

Button Artist

As we are dealing with an executable program, we have to format all buttons so I created a class to set buttons texts and icons, as below.

*----------------------------------------------------------------------*

*       CLASS lcl_button_artist DEFINITION

*----------------------------------------------------------------------*

* This class formats all buttons inside the selection screen

*----------------------------------------------------------------------*

CLASS lcl_button_artist DEFINITION.

  PUBLIC SECTION.

    METHODS format_buttons. " Wrapper method for all protected logic

  PROTECTED SECTION.

    METHODS define_buttons_texts.

    METHODS define_buttons_icons.

ENDCLASS.                    "lcl_button_artist DEFINITION

*----------------------------------------------------------------------*

*       CLASS lcl_button_artist IMPLEMENTATION

*----------------------------------------------------------------------*

*

*----------------------------------------------------------------------*

CLASS lcl_button_artist IMPLEMENTATION.

  METHOD format_buttons.

    me->define_buttons_texts( ).

    me->define_buttons_icons( ).

  ENDMETHOD.                    "format_buttons

  METHOD define_buttons_texts.

    pb_prg1 = 'Book Management'.

    pb_prg2 = 'Z Program with documentation'.

    pb_cfg1 = 'SM30 Configuration'.

    pb_val1 = 'Filtered table'.

  ENDMETHOD.                    "define_buttons_texts

  METHOD define_buttons_icons.

    DATA icon_str TYPE char255.

    CALL FUNCTION 'ICON_CREATE'

      EXPORTING

        name                  = icon_information

*       text                  = ' '

        info                  = ' '

*       ADD_STDINF            = 'X'

      IMPORTING

        result                = icon_str

      EXCEPTIONS

        icon_not_found        = 1

        outputfield_too_short = 2

        OTHERS                = 3.

* The same icon is defined for all buttons. You can change this to have different icons for each button

    pb_prg1i = icon_str.

    pb_prg2i = icon_str.

    pb_cfg1i = icon_str.

    pb_val1i = icon_str.

  ENDMETHOD.                    "define_buttons_icons

ENDCLASS.                    "lcl_button_artist IMPLEMENTATION

The Calling

"I will go wherever you will go"

Different buttons trigger different SAP objects: transacion codes, SM30 maintenance dialogs, documentation popups etc. This can be represented as an interface with multiple classes implementing it. As the song, the dashboard should go wherever the user goes.

*----------------------------------------------------------------------*

*       INTERFACE lif_caller

*----------------------------------------------------------------------*

* This interface defines a generic action caller.

* Classes which implement this interface can call any kind of action

* under different scenarios.

* In this program, these actions are triggered after a button is pressed.

* Depending on the button, a different SAP object will be called.

*----------------------------------------------------------------------*

INTERFACE lif_caller.

  METHODS: call.

ENDINTERFACE.                    "lif_caller

Transactions

*----------------------------------------------------------------------*

*       CLASS lcl_caller_tcode DEFINITION

*----------------------------------------------------------------------*

* This call calls transaction codes stored in sy-ucomm variable.

*----------------------------------------------------------------------*

CLASS lcl_caller_tcode DEFINITION.

  PUBLIC SECTION.

    INTERFACES lif_caller.

    METHODS call_tcode IMPORTING im_ucomm TYPE syst-ucomm.

ENDCLASS.                    "lcl_caller_tcode DEFINITION

*----------------------------------------------------------------------*

*       CLASS lcl_caller_tcode IMPLEMENTATION

*----------------------------------------------------------------------*

*

*----------------------------------------------------------------------*

CLASS lcl_caller_tcode IMPLEMENTATION.

  METHOD lif_caller~call.

    me->call_tcode( sy-ucomm ).

  ENDMETHOD.                    "lif_caller~call

  METHOD call_tcode.

    CALL TRANSACTION im_ucomm.

  ENDMETHOD.                    "call_tcode

ENDCLASS.                    "lcl_invocador_tcode IMPLEMENTATION

Documentation Popup

*----------------------------------------------------------------------*

*       CLASS lcl_caller_documentation DEFINITION

*----------------------------------------------------------------------*

* This class calls the so famous yellow help popup when F1 key is pressed.

* The documentation object to be called is stored in sy-ucomm variable.

*----------------------------------------------------------------------*

CLASS lcl_caller_documentation DEFINITION.

  PUBLIC SECTION.

    INTERFACES lif_caller.

    METHODS call_ducumentation IMPORTING im_ucomm TYPE syst-ucomm.

ENDCLASS.                    "lcl_caller_documentation DEFINITION

*----------------------------------------------------------------------*

*       CLASS lcl_caller_documentation IMPLEMENTATION

*----------------------------------------------------------------------*

*

*----------------------------------------------------------------------*

CLASS lcl_caller_documentation IMPLEMENTATION.

  METHOD lif_caller~call.

    me->call_ducumentation( sy-ucomm ).

  ENDMETHOD.                    "lif_caller~call

  METHOD call_ducumentation.

    CONSTANTS cl_class_objeto TYPE dsysh-dokclass VALUE 'RE'.

    DATA vl_dokname TYPE string.

    vl_dokname = sy-ucomm.

    CALL FUNCTION 'DSYS_SHOW_FOR_F1HELP'

      EXPORTING

*       APPLICATION              = 'SO70'

        dokclass                 = cl_class_objeto

*       DOKLANGU                 = SY-LANGU

        dokname                  = vl_dokname

*       DOKTITLE                 = ' '

*       HOMETEXT                 = ' '

*       OUTLINE                  = ' '

*       VIEWNAME                 = 'STANDARD'

*       Z_ORIGINAL_OUTLINE       = ' '

*       CALLED_FROM_SO70         = ' '

*       SHORT_TEXT               = ' '

*       APPENDIX                 = ' '

*     IMPORTING

*       APPL                     =

*       PF03                     =

*       PF15                     =

*       PF12                     =

*     EXCEPTIONS

*       CLASS_UNKNOWN            = 1

*       OBJECT_NOT_FOUND         = 2

*       OTHERS                   = 3

              .

    IF sy-subrc <> 0.

      MESSAGE 'Documentation not available' TYPE 'E' DISPLAY LIKE 'S'.

    ENDIF.

  ENDMETHOD.                    "chama_documentacao

ENDCLASS.                    "lcl_invocador_documentacao IMPLEMENTATION

View Variant

View variants can be created in SE54 and can be understood as a SM30 dialog with data filtered. In the example available to download at the end of this post, Z_SOUTH_AMERICA is just a view variant including just south america countries from table T005.

*----------------------------------------------------------------------*

*       CLASS lcl_caller_view_variant DEFINITION

*----------------------------------------------------------------------*

* This class is responsible for calling a view variant

* These variants have the ability to call a maintenance dialog for a

* table with pre specified filter criteria.

* This might be useful if you have at least one table to store default

* values for your solution and this table is shared across different

* solutions inside your system.

* This caller is an indirect call for SM30 if you will.

*----------------------------------------------------------------------*

CLASS lcl_caller_view_variant DEFINITION.

  PUBLIC SECTION.

    INTERFACES lif_caller.

    METHODS call_view_variant IMPORTING im_ucomm TYPE syst-ucomm.

ENDCLASS.                    "lcl_caller_view_variant DEFINITION

*----------------------------------------------------------------------*

*       CLASS lcl_caller_view_variant IMPLEMENTATION

*----------------------------------------------------------------------*

*

*----------------------------------------------------------------------*

CLASS lcl_caller_view_variant IMPLEMENTATION.

  METHOD lif_caller~call.

    me->call_view_variant( sy-ucomm ).

  ENDMETHOD.                    "lif_acionador~acionar

  METHOD call_view_variant.

    DATA vl_nome_visao TYPE dd02v-tabname.

    vl_nome_visao = sy-ucomm.

    CALL FUNCTION 'VIEW_MAINTENANCE_CALL'

      EXPORTING

        action                               = 'S' " Visualizacao

*       CORR_NUMBER                          = '          '

*       GENERATE_MAINT_TOOL_IF_MISSING       = ' '

*       SHOW_SELECTION_POPUP                 = ' '

        view_name                            = vl_nome_visao

*       NO_WARNING_FOR_CLIENTINDEP           = ' '

*       RFC_DESTINATION_FOR_UPGRADE          = ' '

*       CLIENT_FOR_UPGRADE                   = ' '

*       VARIANT_FOR_SELECTION                = ' '

*       COMPLEX_SELCONDS_USED                = ' '

*       CHECK_DDIC_MAINFLAG                  = ' '

*       SUPPRESS_WA_POPUP                    = ' '

*     TABLES

*       DBA_SELLIST                          =

*       EXCL_CUA_FUNCT                       =

*     EXCEPTIONS

*       CLIENT_REFERENCE                     = 1

*       FOREIGN_LOCK                         = 2

*       INVALID_ACTION                       = 3

*       NO_CLIENTINDEPENDENT_AUTH            = 4

*       NO_DATABASE_FUNCTION                 = 5

*       NO_EDITOR_FUNCTION                   = 6

*       NO_SHOW_AUTH                         = 7

*       NO_TVDIR_ENTRY                       = 8

*       NO_UPD_AUTH                          = 9

*       ONLY_SHOW_ALLOWED                    = 10

*       SYSTEM_FAILURE                       = 11

*       UNKNOWN_FIELD_IN_DBA_SELLIST         = 12

*       VIEW_NOT_FOUND                       = 13

*       MAINTENANCE_PROHIBITED               = 14

*       OTHERS                               = 15

              .

    IF sy-subrc <> 0.

* MESSAGE ID SY-MSGID TYPE SY-MSGTY NUMBER SY-MSGNO

*         WITH SY-MSGV1 SY-MSGV2 SY-MSGV3 SY-MSGV4.

    ENDIF.

  ENDMETHOD.                    "chama_view_variant

ENDCLASS.                    "lcl_caller_view_variant

Factory Class

We are almost done. Now it's just required to check which class should be instantiated by checking which button was pressed. This can be achieved with a factory class, as below.

*----------------------------------------------------------------------*

*       CLASS lcl_factory_caller DEFINITION

*----------------------------------------------------------------------*

* This class is a factory for a caller. Depending on sy-ucomm value, this

* classes instantiates a proper caller

*----------------------------------------------------------------------*

CLASS lcl_factory_caller DEFINITION CREATE PRIVATE.

  PUBLIC SECTION.

    CLASS-METHODS create_caller

        RETURNING value(re_caller) TYPE REF TO lif_caller.

ENDCLASS.                    "lcl_factory_caller DEFINITION

*----------------------------------------------------------------------*

*       CLASS lcl_factory_caller IMPLEMENTATION

*----------------------------------------------------------------------*

*

*----------------------------------------------------------------------*

CLASS lcl_factory_caller IMPLEMENTATION.

  METHOD create_caller.

    CASE sy-ucomm.

* Transactions

      WHEN  'SPPFDEMO'.

*          OR 'Z_SOL_1'.

        CREATE OBJECT re_caller TYPE lcl_caller_tcode.

* Documentation

      WHEN  'SAPMPPFBOOKDEMO'

*            OR 'Z_SOL_PROG_1'.

            OR 'SAPL0N1S'

            OR 'SAPL0F06'.

        CREATE OBJECT re_caller TYPE lcl_caller_documentation.

* View Variants

      WHEN      'N1ORGPAR'

            OR  'Z_SOUTH_AMERICA'.

        CREATE OBJECT re_caller TYPE lcl_caller_view_variant.

    ENDCASE.

  ENDMETHOD.                    "create_caller

ENDCLASS.                    "lcl_factory_caller IMPLEMENTATION

PUTTING ALL TOGETHER

Now let's just put the pieces together

REPORT  z_oo_dashboard.

INCLUDE z_oo_dashboard_sel. " Selection screen

INCLUDE z_oo_dashboard_cla. " Classes - transactions calls

DATA obj_caller TYPE REF TO lif_caller. " Triggers an action

DATA obj_button_artist TYPE REF TO lcl_button_artist. " A simple formatter for all buttons inside the selecion screen

INITIALIZATION.

  create OBJECT obj_button_artist.

  obj_button_artist->format_buttons( ). " Defines texts and icons

**********************************************************************

* AT SELECTION-SCREEN OUTPUT

**********************************************************************

AT SELECTION-SCREEN OUTPUT.

*--------------------------------------------------------------------*

* Removes execute button from report

  DATA vl_comandos TYPE TABLE OF sy-ucomm.

  APPEND 'ONLI' TO vl_comandos.

  CALL FUNCTION 'RS_SET_SELSCREEN_STATUS'

    EXPORTING

      p_status  = sy-pfkey

    TABLES

      p_exclude = vl_comandos.

*--------------------------------------------------------------------*

**********************************************************************

* AT SELECTION-SCREEN

**********************************************************************

AT SELECTION-SCREEN.

  obj_caller = lcl_factory_caller=>create_caller( ). " Defines which action will be done

  IF obj_caller IS BOUND.

    obj_caller->call( ). " Call specified action

  ENDIF.

SAPLink file

You can file the complete source code below:

http://abap101.com/wp-content/uploads/2013/07/NUGG_OO_MINI_DASHBOARD.nugg_.zip

Conclusion

Creating a dashboard definitely can be useful for your user when your solution gets huge. The ability to adapt and enhance your dashboard easily as your solution gets bigger and bigger is also a huge advantage. So download this code and enjoy it!

I almost forgot to mention.. in case of doubt, hint or feeling that you have to express yourself, please comment!

1 Comment