Skip to Content
Technical Articles
Author's profile photo Uladzislau Pralat

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)

 

 

 

 

 

Assigned tags

      4 Comments
      You must be Logged on to comment or reply to a post.
      Author's profile photo Akash Parikh
      Akash Parikh

      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.

      Author's profile photo Uladzislau Pralat
      Uladzislau Pralat
      Blog Post Author

      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

      Author's profile photo Hendra Mahadina
      Hendra Mahadina

      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

      Author's profile photo Uladzislau Pralat
      Uladzislau Pralat
      Blog Post Author

      Hi Hendra,

      can you please share your example with SAP Community?

      Regards, Uladzislau