Skip to Content
Technical Articles

Get All Your BW Customer-Exit Variables with One ABAP Statement

How BW Customer-Exit Variables are programmed? Usually it is a bunch of nested CASE, IF statements and lots I_T_VAR_RANGE parameter APPEND statements / assignments. Why you need to have tons of I_T_VAR_RANGE parameter APPEND / assignments all over your program code?

In my sample code below I assign I_T_VAR_RANGE parameter only once and code all logic in  COND, SWITCH statements and function method calls.

METHOD if_rsroa_variables_exit_badi~process.

  TRY.
    c_t_range =
      COND #( WHEN NOT c_t_range[] IS INITIAL
              THEN c_t_range
              WHEN i_step = 1
              THEN COND #( WHEN i_vnam = 'CPL_PRODH2'
                           THEN get_prodh2( )
                           WHEN i_vnam = 'CPL_MONTH1'
                           THEN get_month( ) )
              WHEN i_step = 2
              THEN COND #( WHEN i_vnam = 'CPL_MONTH2'
                           THEN VALUE #( ( sign = 'I'
                                           opt  = 'BT'
                                           low  = |{ i_t_var_range[ vnam = 'CPL_MONTH1' ]-low+0(4) - 1 }{ i_t_var_range[ vnam = 'CPL_MONTH1' ]-low+4(2) }|
                                           high = |{ i_t_var_range[ vnam = 'CPL_MONTH1' ]-high+0(4) - 1 }{ i_t_var_range[ vnam = 'CPL_MONTH1' ]-high+4(2) }| ) )
                           WHEN i_vnam = 'CPL_HCUST_TOPN'
                           THEN get_hcust( i_t_var_range )
                           WHEN i_vnam = 'CPL_FYEAR1'
                           THEN COND #( WHEN get_fyear( CONV /bi0/oicalmonth( i_t_var_range[ vnam = 'CPL_MONTH1' ]-low ) ) =
                                             get_fyear( CONV /bi0/oicalmonth( i_t_var_range[ vnam = 'CPL_MONTH1' ]-high ) )
                                        THEN VALUE #( ( sign = 'I'
                                                        opt  = 'EQ'
                                                        low  = get_fyear( CONV /bi0/oicalmonth( i_t_var_range[ vnam = 'CPL_MONTH1' ]-low ) ) ) ) )
                           WHEN i_vnam = 'CPL_FYEAR2'
                           THEN COND #( WHEN get_fyear( CONV /bi0/oicalmonth( i_t_var_range[ vnam = 'CPL_MONTH1' ]-low ) ) =
                                             get_fyear( CONV /bi0/oicalmonth( i_t_var_range[ vnam = 'CPL_MONTH1' ]-high ) )
                                        THEN VALUE #( ( sign = 'I'
                                                        opt  = 'EQ'
                                                        low  = CONV /bi0/oifiscyear( get_fyear( CONV /bi0/oicalmonth( i_t_var_range[ vnam = 'CPL_MONTH1' ]-low ) ) - 1 ) ) ) )
                           WHEN i_vnam = 'CPL_CURR'
                           THEN get_month_text( iv_vnam       = 'CPL_MONTH1'
                                                i_t_var_range = i_t_var_range )
                           WHEN i_vnam = 'CPL_PREV'
                           THEN get_month_text( iv_vnam       = 'CPL_MONTH2'
                                                i_t_var_range = i_t_var_range ) )
              WHEN i_step = 3
              THEN COND #( WHEN ( ( i_t_var_range[ vnam = 'CPL_MONTH1' ]-high+0(4) -  i_t_var_range[ vnam = 'CPL_MONTH1' ]-low+0(4) ) > 1 ) OR
                                ( ( ( i_t_var_range[ vnam = 'CPL_MONTH1' ]-high+0(4) -  i_t_var_range[ vnam = 'CPL_MONTH1' ]-low+0(4) ) = 1 ) AND
                                  ( i_t_var_range[ vnam = 'CPL_MONTH1' ]-high+4(2) >= i_t_var_range[ vnam = 'CPL_MONTH1' ]-low+4(2) ) )
                           THEN validate_month( ) ) ).
  CATCH cx_sy_itab_line_not_found.
  ENDTRY.

ENDMETHOD.

Note: the same implementation of RSROA_VARIABLES_EXIT enhancement spot can populate / validate characteristic value variables, populate text variables, etc

 

Below is enhancements spot implementation class code with all function methods and constructor

class ZCL_RSROA_VAR_EXIT_CPL definition
  public
  final
  create public .

public section.

  interfaces IF_BADI_INTERFACE .
  interfaces IF_RSROA_VARIABLES_EXIT_BADI .

  methods CONSTRUCTOR .
protected section.
private section.

  data DATE type DATS .

  methods GET_FYEAR
    importing
      !IV_MONTH type /BI0/OICALMONTH
    returning
      value(RV_FYEAR) type /BI0/OIFISCYEAR .
  methods GET_MONTH
    returning
      value(RT_RANGE) type RSR_T_RANGESID .
  methods GET_HCUST
    importing
      !IT_VAR_RANGE type RRS0_T_VAR_RANGE
    returning
      value(RT_RANGE) type RSR_T_RANGESID .
  methods GET_PRODH2
    returning
      value(RT_RANGE) type RSR_T_RANGESID .
  methods GET_MONTH_TXT
    importing
      !IV_MONTH type I
    returning
      value(RV_MONTH_TXT) type STRING .
  methods GET_MONTH_TEXT
    importing
      !IV_VNAM type RSZVNAM
      !I_T_VAR_RANGE type RRS0_T_VAR_RANGE
    returning
      value(RT_RANGE) type RSR_T_RANGESID .
  methods VALIDATE_MONTH
    returning
      value(RT_RANGE) type RSR_T_RANGESID .
ENDCLASS.



CLASS ZCL_RSROA_VAR_EXIT_CPL IMPLEMENTATION.


* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Public Method ZCL_RSROA_VAR_EXIT_CPL->CONSTRUCTOR
* +-------------------------------------------------------------------------------------------------+
* +--------------------------------------------------------------------------------------</SIGNATURE>
METHOD constructor.

  date = COND #( WHEN sy-sysid = 'DEV' OR sy-sysid = 'TST'
                 THEN ( CONV dats( |{ sy-datum+0(4) - 2 }{ sy-datum+4(2) }01| ) - 1 )
                 WHEN sy-sysid = 'PRD' THEN CONV dats( |{ sy-datum+0(6) }01| ) - 1 ).

ENDMETHOD.


* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Private Method ZCL_RSROA_VAR_EXIT_CPL->GET_FYEAR
* +-------------------------------------------------------------------------------------------------+
* | [--->] IV_MONTH                       TYPE        /BI0/OICALMONTH
* | [<-()] RV_FYEAR                       TYPE        /BI0/OIFISCYEAR
* +--------------------------------------------------------------------------------------</SIGNATURE>
METHOD get_fyear.

  rv_fyear = COND #( WHEN iv_month+4(2) BETWEEN '01' AND '03'
                     THEN iv_month+0(4) - 1
                     ELSE iv_month+0(4) ).

ENDMETHOD.


* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Private Method ZCL_RSROA_VAR_EXIT_CPL->GET_HCUST
* +-------------------------------------------------------------------------------------------------+
* | [--->] IT_VAR_RANGE                   TYPE        RRS0_T_VAR_RANGE
* | [<-()] RT_RANGE                       TYPE        RSR_T_RANGESID
* +--------------------------------------------------------------------------------------</SIGNATURE>
METHOD get_hcust.
DATA: ws_return TYPE bapiret2.
DATA: wt_bil TYPE t_bil.

  DATA(wt_selection) =
    VALUE zt_bapif4b(
      FOR wa_var_range IN it_var_range
         WHERE ( iobjnm <> '0CALDAY' AND vnam <> 'CPL_MONTH2' )
        ( select_fld = wa_var_range-iobjnm
           sign       = wa_var_range-sign
           option     = wa_var_range-opt
           low        = wa_var_range-low
           high       = wa_var_range-high ) ).
  APPEND VALUE #( select_fld = 'ZKITCOMP' sign = 'I' option = 'EQ' low = ' ' ) TO wt_selection.
  APPEND VALUE #( select_fld = 'ZKITCOMP' sign = 'I' option = 'EQ' low = 'C' ) TO wt_selection.


* Get Billing Data
	...

  SORT wt_bil BY znetval1 DESCENDING.
  LOOP AT wt_bil INTO DATA(wa_bil) FROM 1 TO 10.
    APPEND VALUE #( sign = 'I'
                    opt  = 'EQ'
                    low  = wa_bil-0sold_to__hcustomer ) TO rt_range.
  ENDLOOP.

ENDMETHOD.


* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Private Method ZCL_RSROA_VAR_EXIT_CPL->GET_MONTH
* +-------------------------------------------------------------------------------------------------+
* | [<-()] RT_RANGE                       TYPE        RSR_T_RANGESID
* +--------------------------------------------------------------------------------------</SIGNATURE>
METHOD get_month.

  rt_range = VALUE #( ( sign = 'I'
                        opt  = 'BT'
                        low  = |{ COND numc4( WHEN date+4(2) BETWEEN '01' AND '03'
                                              THEN date+0(4) - 1
                                              ELSE date+0(4) ) }04|
                        high = |{ date+0(6) }| ) ).

ENDMETHOD.


* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Private Method ZCL_RSROA_VAR_EXIT_CPL->GET_MONTH_TEXT
* +-------------------------------------------------------------------------------------------------+
* | [--->] IV_VNAM                        TYPE        RSZVNAM
* | [--->] I_T_VAR_RANGE                  TYPE        RRS0_T_VAR_RANGE
* | [<-()] RT_RANGE                       TYPE        RSR_T_RANGESID
* +--------------------------------------------------------------------------------------</SIGNATURE>
METHOD get_month_text.

  rt_range = COND #( WHEN i_t_var_range[ vnam = iv_vnam ]-low+4(2) = '04' AND
                          i_t_var_range[ vnam = iv_vnam ]-high+4(2) = '03' AND
                          i_t_var_range[ vnam = iv_vnam ]-high+0(4) - i_t_var_range[ vnam = iv_vnam ]-low+0(4) = 1
                     THEN VALUE #( ( sign = 'I'
                                     opt  = 'EQ'
                                     low  = |FY { get_fyear( CONV /bi0/oicalmonth( i_t_var_range[ vnam = iv_vnam ]-low ) ) }| ) )
                     WHEN ( i_t_var_range[ vnam = iv_vnam ]-low+4(2) = '04' AND i_t_var_range[ vnam = iv_vnam ]-high+4(2) = '06' ) OR
                          ( i_t_var_range[ vnam = iv_vnam ]-low+4(2) = '07' AND i_t_var_range[ vnam = iv_vnam ]-high+4(2) = '09' ) OR
                          ( i_t_var_range[ vnam = iv_vnam ]-low+4(2) = '10' AND i_t_var_range[ vnam = iv_vnam ]-high+4(2) = '12' ) OR
                          ( i_t_var_range[ vnam = iv_vnam ]-low+4(2) = '01' AND i_t_var_range[ vnam = iv_vnam ]-high+4(2) = '03' )
                     THEN VALUE #( ( sign = 'I'
                                     opt  = 'EQ'
                                     low  = |FQ{ SWITCH #( i_t_var_range[ vnam = iv_vnam ]-low+4(2)
                                                   WHEN '04' THEN '1'
                                                   WHEN '07' THEN '2'
                                                   WHEN '10' THEN '3'
                                                   WHEN '01' THEN '4' ) } { get_fyear( CONV /bi0/oicalmonth( i_t_var_range[ vnam = iv_vnam ]-low ) ) }| ) )
                     WHEN i_t_var_range[ vnam = iv_vnam ]-low+4(2) = '04'
                     THEN VALUE #( ( sign = 'I'
                                     opt  = 'EQ'
                                     low  = |FTLM { get_fyear( CONV /bi0/oicalmonth( i_t_var_range[ vnam = iv_vnam ]-low ) ) }| ) )
                     WHEN i_t_var_range[ vnam = iv_vnam ]-low = i_t_var_range[ vnam = iv_vnam ]-high
                     THEN VALUE #( ( sign = 'I'
                                     opt  = 'EQ'
                                     low  = |{ get_month_txt( CONV i( i_t_var_range[ vnam = iv_vnam ]-low+4(2) ) ) } { i_t_var_range[ vnam = iv_vnam ]-low+0(4) }| ) )
                     ELSE VALUE #( ( sign = 'I'
                                     opt  = 'EQ'
                                     low  = SWITCH #( iv_vnam
                                              WHEN 'CPL_MONTH1' THEN 'Current'
                                              WHEN 'CPL_MONTH2' THEN 'Previous' ) ) ) ).

ENDMETHOD.


* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Private Method ZCL_RSROA_VAR_EXIT_CPL->GET_MONTH_TXT
* +-------------------------------------------------------------------------------------------------+
* | [--->] IV_MONTH                       TYPE        I
* | [<-()] RV_MONTH_TXT                   TYPE        STRING
* +--------------------------------------------------------------------------------------</SIGNATURE>
METHOD get_month_txt.

  rv_month_txt =
    SWITCH #( iv_month
      WHEN 1  THEN 'Jan'
      WHEN 2  THEN 'Feb'
      WHEN 3  THEN 'Mar'
      WHEN 4  THEN 'Apr'
      WHEN 5  THEN 'May'
      WHEN 6  THEN 'Jun'
      WHEN 7  THEN 'Jul'
      WHEN 8  THEN 'Aug'
      WHEN 10 THEN 'Sep'
      WHEN 11 THEN 'Oct'
      WHEN 12 THEN 'Nov' ).

ENDMETHOD.


* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Private Method ZCL_RSROA_VAR_EXIT_CPL->GET_PRODH2
* +-------------------------------------------------------------------------------------------------+
* | [<-()] RT_RANGE                       TYPE        RSR_T_RANGESID
* +--------------------------------------------------------------------------------------</SIGNATURE>
METHOD get_prodh2.

  SELECT /bic/zzdiv1 AS zprodh1
  INTO TABLE @DATA(wt_prodh1)
  FROM zzdiv1.
  rt_range =
    VALUE #( FOR wa_prodh1 IN wt_prodh1 (
      sign = 'I' opt = 'CP' low = |{ wa_prodh1-zprodh1 }*| ) ).

ENDMETHOD.


* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Public Method ZCL_RSROA_VAR_EXIT_CPL->IF_RSROA_VARIABLES_EXIT_BADI~PROCESS
* +-------------------------------------------------------------------------------------------------+
* | [--->] I_VNAM                         TYPE        RSZGLOBV-VNAM
* | [--->] I_VARTYP                       TYPE        RSZGLOBV-VARTYP
* | [--->] I_IOBJNM                       TYPE        RSZGLOBV-IOBJNM
* | [--->] I_S_COB_PRO                    TYPE        RSD_S_COB_PRO
* | [--->] I_S_RKB1D                      TYPE        RSR_S_RKB1D
* | [--->] I_PERIV                        TYPE        RRO01_S_RKB1F-PERIV
* | [--->] I_T_VAR_RANGE                  TYPE        RRS0_T_VAR_RANGE
* | [--->] I_STEP                         TYPE        I (default =0)
* | [<-->] C_T_RANGE                      TYPE        RSR_T_RANGESID(optional)
* | [<-->] C_NO_SCREEN                    TYPE        RS_BOOL(optional)
* | [<-->] C_CHECK_AGAIN                  TYPE        RS_BOOL(optional)
* | [<-->] C_S_CUSTOMER                   TYPE        RRO04_S_CUSTOMER(optional)
* | [!CX!] CX_RS_ERROR
* +--------------------------------------------------------------------------------------</SIGNATURE>
METHOD if_rsroa_variables_exit_badi~process.

  TRY.
    c_t_range =
      COND #( WHEN NOT c_t_range[] IS INITIAL
              THEN c_t_range
              WHEN i_step = 1
              THEN COND #( WHEN i_vnam = 'CPL_PRODH2'
                           THEN get_prodh2( )
                           WHEN i_vnam = 'CPL_MONTH1'
                           THEN get_month( ) )
              WHEN i_step = 2
              THEN COND #( WHEN i_vnam = 'CPL_MONTH2'
                           THEN VALUE #( ( sign = 'I'
                                           opt  = 'BT'
                                           low  = |{ i_t_var_range[ vnam = 'CPL_MONTH1' ]-low+0(4) - 1 }{ i_t_var_range[ vnam = 'CPL_MONTH1' ]-low+4(2) }|
                                           high = |{ i_t_var_range[ vnam = 'CPL_MONTH1' ]-high+0(4) - 1 }{ i_t_var_range[ vnam = 'CPL_MONTH1' ]-high+4(2) }| ) )
                           WHEN i_vnam = 'CPL_HCUST_TOPN'
                           THEN get_hcust( i_t_var_range )
                           WHEN i_vnam = 'CPL_FYEAR1'
                           THEN COND #( WHEN get_fyear( CONV /bi0/oicalmonth( i_t_var_range[ vnam = 'CPL_MONTH1' ]-low ) ) =
                                             get_fyear( CONV /bi0/oicalmonth( i_t_var_range[ vnam = 'CPL_MONTH1' ]-high ) )
                                        THEN VALUE #( ( sign = 'I'
                                                        opt  = 'EQ'
                                                        low  = get_fyear( CONV /bi0/oicalmonth( i_t_var_range[ vnam = 'CPL_MONTH1' ]-low ) ) ) ) )
                           WHEN i_vnam = 'CPL_FYEAR2'
                           THEN COND #( WHEN get_fyear( CONV /bi0/oicalmonth( i_t_var_range[ vnam = 'CPL_MONTH1' ]-low ) ) =
                                             get_fyear( CONV /bi0/oicalmonth( i_t_var_range[ vnam = 'CPL_MONTH1' ]-high ) )
                                        THEN VALUE #( ( sign = 'I'
                                                        opt  = 'EQ'
                                                        low  = CONV /bi0/oifiscyear( get_fyear( CONV /bi0/oicalmonth( i_t_var_range[ vnam = 'CPL_MONTH1' ]-low ) ) - 1 ) ) ) )
                           WHEN i_vnam = 'CPL_CURR'
                           THEN get_month_text( iv_vnam       = 'CPL_MONTH1'
                                                i_t_var_range = i_t_var_range )
                           WHEN i_vnam = 'CPL_PREV'
                           THEN get_month_text( iv_vnam       = 'CPL_MONTH2'
                                                i_t_var_range = i_t_var_range ) )
              WHEN i_step = 3
              THEN COND #( WHEN ( ( i_t_var_range[ vnam = 'CPL_MONTH1' ]-high+0(4) -  i_t_var_range[ vnam = 'CPL_MONTH1' ]-low+0(4) ) > 1 ) OR
                                ( ( ( i_t_var_range[ vnam = 'CPL_MONTH1' ]-high+0(4) -  i_t_var_range[ vnam = 'CPL_MONTH1' ]-low+0(4) ) = 1 ) AND
                                  ( i_t_var_range[ vnam = 'CPL_MONTH1' ]-high+4(2) >= i_t_var_range[ vnam = 'CPL_MONTH1' ]-low+4(2) ) )
                           THEN validate_month( ) ) ).
  CATCH cx_sy_itab_line_not_found.
  ENDTRY.

ENDMETHOD.


* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Private Method ZCL_RSROA_VAR_EXIT_CPL->VALIDATE_MONTH
* +-------------------------------------------------------------------------------------------------+
* | [<-()] RT_RANGE                       TYPE        RSR_T_RANGESID
* +--------------------------------------------------------------------------------------</SIGNATURE>
METHOD validate_month.

  CALL FUNCTION 'RRMS_MESSAGE_HANDLING'
       EXPORTING
            i_class  = 'OO'
            i_type   = 'E'
            i_number = '000'
            i_msgv1  = 'Maximum 12 months range can be selected'.
* RAISE EXCEPTION TYPE cx_rs_error.

ENDMETHOD.
ENDCLASS.

Note: do not forget to update enhancement spot filter (Space – characteristic value validation, 1TEXT – for text values)

 

 

 

 

 

4 Comments
You must be Logged on to comment or reply to a post.
  • Hi Uladzislau,

     

    Nice Blog.

     

    one question, i believe while creating customer exists using BADI, filter value is mandatory.

    so if you are embedding all variable code in one place, what you are using as your filter?

     

    Thanks.

    • Hi Akash,

      using InfoObject filter with BW Variable BADI is optional, but highly recommend. I have multiple BW Variable BADI implementations (common variables and per specific application area) and limit a scope of each implementation using InfoObject filter.

      Regards, Uladzislau

  • Hi Mr. Uladzislau,

     

    If you said that ” your ultimate goal is to make BW Customer-Exit Variable code more readable and maintainable”.

    Why don’t’ you use a table as a tool to replace case or if statement more readable?

     

    Regards,

    Hendra Mahadina