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: 
Juwin
Active Contributor

We all have heard about dynamic conditions in WHERE clauses (Dynamic where clause - ABAP Development - SCN Wiki), dynamic READ statements (Dynamic WHERE in READ TABLE | SCN), dynamic internal tables/ structures/ ALV (Tutorial abap - Code for Dynamic Alv grid - Code Gallery - SCN Wiki), in short dynamic programming (Dynamic Programming -  Application Development on AS ABAP - SAP Library)...

But, when I searched about dynamic conditions in IF statement, I couldn't find many hits. Some of the hits said, it was not possible, some said to use ranges, and some others said it required dynamic subroutine generation etc.

I have used EVAL_FORMULA function module before (Program to evaluate formula in a string - ABAP Development - SCN Wiki). But, I haven't had much success with TEXT operations, using this function module.

So, I am here to discuss a method to achieve dynamic IF conditions in ABAP.

Interfaces used:

IF_FOBU_CONNECTOR

IF_FOEV_CONNECTOR

Classes used:

CL_FOBU_FORMULA - Formula Builder

CL_FOEV_FORMULA - Formula Evaluator

This same method can be used to evaluate dynamic formulae, just by changing the return type of the method. Since, I have used return type as BOOLEAN, I expect a TRUE or FALSE value to be returned by the method.

Global Class ZCL_EVALUATE_DYNAMIC_CONDITION:

    1  class zcl_evaluate_dynamic_condition definition

    2    public

    3    final

    4    create public .

    5 

    6    public section.

    7 

    8      interfaces if_fobu_connector .

    9      interfaces if_foev_connector .

   10 

   11      types:begin            of   ty_field_values .

   12      types name             type string.

   13      types data             type ref to data.

   14      types type             type string.

   15      types end              of   ty_field_values .

   16      types:tyt_field_values type standard table

   17            of ty_field_values with non-unique key table_line .

   18 

   19      class-methods factory

   20        returning

   21          value(rv_evaluator) type ref to zcl_evaluate_dynamic_condition .

   22      methods calculate

   23        importing

   24          value(it_dictionary) type tyt_field_values

   25          value(iv_formula)    type string

   26        returning

   27          value(rv_value)      type boolean .

   28    protected section.

   29    private section.

   30 

   31      data    dictionary       type tyt_field_values .

   32  endclass.

   33 

   34  class zcl_evaluate_dynamic_condition implementation.

   35 

   36    method calculate.

   37      data: lr_env     type ref to if_foev_connector,

   38            lr_fenv    type ref to if_fobu_connector,

   39            lr_formula type ref to cl_fobu_formula,

   40            lr_runtime type ref to cl_foev_formula.

   41 

   42      dictionary      =  it_dictionary.

   43      lr_env          ?= me.

   44      lr_fenv         ?= me.

   45      cl_fobu_formula=>create(

   46        exporting

   47          im_tech_names   = abap_true

   48          im_environment  = lr_fenv

   49          im_desired_type = 'BOOLEAN' "<<<<<

                 "Change this return type to use for other purposes

   50          io_fobu_storage = cl_fobu_storage=>get_instance( )

   51        importing

   52          ex_formula      = lr_formula ).

   53      lr_formula->parse( iv_formula ).

   54      lr_runtime       = cl_foev_formula=>load_from_fobu(

   55                           im_formula     = lr_formula

   56                           im_environment = lr_env ).

   57      data(lv_resuld)  = lr_runtime->evaluate( ).

   58      assign lv_resuld->* to field-symbol(<res>).

   59      rv_value         = <res>.

   60    endmethod.

   61 

   62    method factory.

   63      create object rv_evaluator.

   64    endmethod.

   65 

   66    method if_fobu_connector~check.

   67    endmethod.

   68 

   69    method if_fobu_connector~get.

   70    endmethod.

   71 

   72    method if_fobu_connector~get_all_operands.

   73    endmethod.

   74 

   75    method if_fobu_connector~parse_op_get.

   76      read table dictionary into data(meaning)

   77           with key name = ch_tech_name.

   78      if sy-subrc eq 0.

   79        ex_type  = meaning-type.

   80        ex_token = cl_fobu_formula=>c_token_appl_1.

   81      endif.

   82    endmethod.

   83 

   84    method if_fobu_connector~pushbuttons_get.

   85    endmethod.

   86 

   87    method if_fobu_connector~pushbutton_op_get.

   88    endmethod.

   89 

   90    method if_foev_connector~evaluate.

   91      read table dictionary into data(meaning)

   92           with key name = im_fieldname.

   93      if sy-subrc eq 0.

   94        assign meaning-data->* to field-symbol(<fld>).

   95        create data re_result like <fld>.

   96        assign re_result->* to field-symbol(<res>).

   97        <res> = <fld>.

   98      else.

   99        raise exception type cx_foev_formula_invalid

  100          exporting

  101            textid = |{ im_fieldname } field was not found in dictionary|.

  102      endif.

  103    endmethod.

  104  endclass.

Explanation:

  • IF_FOBU_CONNECTOR~PARSE_OP_GET helps in specifying the field types and token type, based on DICTIONARY entries.
  • IF_FOEV_CONNECTOR~EVALUATE helps in converting the fieldnames into values, based on the DICTIONARY entries.
  • LT_FIELDVALUES holds the values of all possible fields that may be used in the formula. Here, since I already know what are the fields used in my formula, I am passing only these values. This is stored in the DICTIONARY, so that the above methods may use it.
  • In the code below, I am passing a constant formula to the method, but purpose of this method is to analyze any dynamic text formula.

Example usage:

    1  class zcl_evaluate_dynamic_condition

    2        definition load.

    3  try.

    4    data:lt_fieldvalues

    5      type zcl_evaluate_dynamic_condition=>tyt_field_values.

    6    lt_fieldvalues = value #( ( name = 'PLAAB'

    7                              type = 'MDPS-PLAAB'

    8                              data = ref #( gs_mdps-plaab ) )

    9                            ( name = 'DELKZ'

   10                              type = 'MDPS-DELKZ'

   11                              data = ref #( gs_mdps-delkz ) )

   12                            ( name = 'LIFNR'

   13                              type = 'MDPS-LIFNR'

   14                              data = ref #( gs_mdps-lifnr ) )

   15                            ( name = 'PLUMI'

   16                              type = 'MDPS-PLUMI'

   17                              data = ref #( gs_mdps-plumi ) ) ).

   18 

   19    if zcl_evaluate_dynamic_condition=>factory( )->calculate(

   20      iv_formula     = |PLAAB = '02' AND DELKZ = 'BB'

                            AND LIFNR <> '' AND PLUMI = '-'|

   21      it_fieldvalues = lt_fieldvalues ) = abap_true.

   22      continue.

   23    endif.

   24  catch cx_root.

   25  endtry.

4 Comments