Skip to Content

BEx-Userexits reloaded

After the initial release of the BI-Tools framework for BEx-Exitvariables in Easy implementation of BEx-Userexit-Variables I got a lot of useful comments and suggestions. And finally, I realized, that I omit a detailed discussion and implementation of the I_STEP 3 ( check after variable-screen ).

Please read first my first blog, because there are a lot more informations about the process and the variable implemenation. This blog talks mostly about experiences and refactoring.

Existing experiences

I have talked to some people, which are using this framework and I have seen some other implementations based on BADI or function modules.

When introducing the object-oriented approach, you can obtain some advantages:

  • Traceability: Every Variable is clearly defined and can be relocated very fast ( without scanning a lot of ABAP coding)
  • Self-documenting Implementation: The variable-interface has been defined for an easy use and not for encapsulating the technical customer-exit interface
  • Reusablitiy: Reduce variable code by inheritance and specify only the necessary code within your concrete variable
  • Stability: If one of the variables has a failure, just this coding is not usable. If you have another approach like includes or big function-groups, this is not guaranteed by default.
  • Testability: Using ABAPUnit with ABAP OO-Bex-Variables is very easy and efficient.

The usage of the BEx-Variables framework has also shown, that an object-oriented approach is easier than plain function modules, if a clear interface is used. I found one example, where even young developers without a lot of development knowledge implemented BEx-Variables.

Why reloaded?

The original implementation has two problems:

  1. The I_STEP = 3 has been implemented as “normal” variable instance and so it has not been very much possiblities to configure and implement this for special queries/infoproviders. This leads to the situation, that all coding has been implemented in one variable-class which handled a lot of different use-cases (and this has not been the original idea of “Separations of concerns”).
  2. A spelling mistaked has been slipped into the naming of the methods – so this could lead into a misunderstanded usage when implementing authority-variables.

So, I enhanced the existing solution and perform a small but effective refactoring. The actual code is checked into code-exchange and can be installed via SAPLink.


Instead of having one interface, which implement all steps, I decided to split the existing variable-interface into two interfaces:

  • The existing variable interface – without step 3 ( and renaming method for i_step = 0)
  • A new check-interface handling I_STEP = 3

A short look into the UML-structure:


As you may notice there is another new class called “ZCL_BIU001_CHECK_COLLECTION”. This has been necessary, because a check can be resolved through a infoprovider assignment or a special query. Within the new customizing it is possible, to define checks based upon those two criterias. Not enough: these parameters could be configured as pattern-based parameters, so you can specify a special check for a class of queries / infoproviders.


In the following, I will show the main changes.

Variable-Interface (BTW: I love the new corbu design – well done πŸ˜‰ )




Additional, the variable-include has been enhanced (a little bit πŸ˜‰ ):

*&  Include           ZXRSRU01
  lcx_exception  TYPE REF TO zcx_biu001_execution_failed,
  lc_check       TYPE REF TO zif_biu001_check,
  lc_variable    TYPE REF TO zif_biu001_variable.
* Special treatment of check in i_step = 3
    IF i_step <> 3. "Sorry for this...
* Every variable is encapsulated through an atomic instance
      lc_variable = zcl_biu001_var_factory=>get_var_instance( i_vnam ).
      IF lc_variable IS BOUND.
            i_vartyp   = i_vartyp
            i_iobjnm   = i_iobjnm
            is_cob_pro = i_s_cob_pro
            is_rkb1d   = i_s_rkb1d
            i_periv    = i_periv
        CASE i_step.
          WHEN 0.
            e_t_range = lc_variable->authority_check( ).
          WHEN 1.
            e_t_range = lc_variable->before_variable_screen( ).
          WHEN 2.
            e_t_range = lc_variable->after_variable_screen( i_t_var_range ).
* Check the variables via a check-instance. If more than one instance is available,
* a collection is automatically used.
      lc_check = zcl_biu001_var_factory=>get_check_instance( i_s_rkb1d ).
      IF lc_check IS BOUND.
        lc_check->value_check( i_t_var_range ).
  CATCH zcx_biu001_execution_failed INTO lcx_exception.
        i_class  = lcx_exception->if_t100_message~t100key-msgid
        i_type   = rs_c_error
        i_number = lcx_exception->if_t100_message~t100key-msgno
        i_msgv1  = lcx_exception->if_t100_message~t100key-attr1
        i_msgv2  = lcx_exception->if_t100_message~t100key-attr2
        i_msgv3  = lcx_exception->if_t100_message~t100key-attr3
        i_msgv4  = lcx_exception->if_t100_message~t100key-attr4.
    RAISE no_replacement.


The customizing has been changed, so that there are two customizing tables: One for the variables and one for the checks.



I would suggest to use them together in one view-cluster. And if you defined the views, think about the DDIC capabilities like search-helps, maintenance-views, foreign-keys. Through the usage of ABAP Interfaces, it is possible, to check at customizing time, if a class implements the correct interface!


I use the described framework intensively and I like the simple usage and the fact, that the original very technical calling has been hidden by two suitable interfaces.

All the coding and documentation will be found within the code-exchange area “BI-Tools”: Please do not hesitate to join or ask any questions about implementation details or how to install it. I have attached the current nugget to this blog.

Have fun!

You must be Logged on to comment or reply to a post.
    • Hello Michael,

      I do not know, why the current nugget is recognized as binary file. Perhaps it depends on my used svn-tool. I will attach the nugget to this blog. If you can manage to get an svn-access to the BI-Tools project, you can checkout the file correctly.

      Kind regards,


      • Hi Hendrik,

        i can't find your code-exchance content anymore.

        It seems they did a release upgrade, and some content got lost.

        If possible, please re-upload your great content there.

        In the meantime, I will try to install it via nugget.



    • Hi Michael,

      Just to add i have implemented the code written in .nugg file downloaded from scn.

      you have to first create the program written in notepad file of SAPLINK.

      Execute that program and then give the .nugg file path. program will be generated automatically by the name given in .nugg file.


      Deepak Machal

  • Hi,

    Thanks for sharing.

    One question:

    Why not implementing a new customer/internal BAdI (definition) instead of custom factory/customizing table?

  • Hi Hendrik,

    there is a function module missing in your attached nugget:


    It is not possible to activate the searchhelp.

    If possible, please update your nugget.

    Thanks and regards

    Daniel Klein


    Ok, a bit off topic. But does anybody have any Idea who I do NOT get I_STEP : 2 ?

    (not even in the debugger). I get step 1 & 3. But it always goes directly from

    step 1 to 3 (even in the debugger)

    BW system is SAP ABAP/BASIS : SAPKA70018

    & BW: SAPKW70020

    Regards, JRE

      • Dear Daniel,

        I actually understand that condition. However (now it comes... πŸ™‚

        STEP 2 will appear when the same variable could not be filled at I_STEP=1  !?

        AND 'the restricted characteristic is not Mandatory NOR does not has another (compounding/connected) Mandatory Characteristic'.

        In my case: I created 2 (user Exit) variables on 0FISCPER. Unfortunately when using 0FISCPER in a restriction: the use of 0FISCVARNT is mandatory in that same restriction (in the SELection) (although I always fill it with a Constant value).

        For the standard coding (BEX Query processor) is this reason enough to skip a I_STEP 2 event. You simply do not get a I_STEP = 2 event here.


        I Deleted my Characteristic structure on ZFISCPER (which is related to 0FISCPER, so it has the same contrains). Added 0CALMONTH in the cube (and filled it from 0FISCPER). Then added a new (Characteristic) structure in the Query (in Columns) where I added a new SELection for 0CALMONTH restricting it with a value range with 2 variables (Hidden & type User Exit). For these Variables a I_STEP = 2 event does appear.

        Where I fill these (0CALMONTH) Variables with YYYYMM using FM: FIRST_DAY_IN_PERIOD_GET and some additonal coding to convert 0FISCPER variable (Inputted by the user in the Execution of the Query) by reading of course first I_T_VAR_RANGE for my 0FISCPER Variables values (YYYYPPP).

        Now I can show in my columns (and) the correct Month and the keyfigures for that month (which was required). I'm showing more months including 'Year to date' keyfigures (for the selected month/period by using the 'OFFSET' of a Variable restriction.

        I will also try the following statements from the link you gave:

        You can insert the following statements to force the variable to be executed

        with I_STEP=2 and not I_STEP=1.

        CASE I_VNAM.

        IF I_STEP <> 2.

          RAISE no_processing.


        Have no clue what is will do, just have to debug it and see what is does and how I can use it (without interupting the regular Query execution).

        Thanks for your help!!!


        (Jos Reithofer, Netherlands)

  • Hi Hendrik,

    your framework works very well, thank you!

    Here are my remarks:

    1. I created a new class as a subclass of ZCL_BIU001_VAR_ABSTRACT. Not your fault, but by doubleclicking (as usually) to navigate into the method coding, I ended up adding my BEFORE_VARIABLE_SCREEN code to the upper class instead of my new subclass ('redefine')...

    To avoid this in the future, I added a big 'DO NOT ADD CODING HERE' warning in the method codings (exception: in INITIALIZE it's OK) of the upper class.

    2. Method 'INITIALIZE' of ZCL_BIU001_VAR_ABSTRACT is empty in the nugget, is this your intention? I expected that you would pass the actual parameters to the (already existing!) class attributes:

         p_vartyp    = i_vartyp.
         p_iobjnm    = i_iobjnm.
         ps_cob_pro  = is_cob_pro.
         ps_rkb1d    = is_rkb1d.
         p_periv     = i_periv.

    3. All but one class attribute of ZCL_BIU001_VAR_ABSTRACT came as 'Private'. I had to set them to 'Protected' to use them in my subclasses.