Skip to Content

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.

To report this post you need to login first.

3 Comments

You must be Logged on to comment or reply to a post.

  1. Jacques Nomssi

    Hello Juwin,

    thanks for taking the time to explain how to use the build in ABAP formula builder/interpreter.  I have started checking how it is used in the system to add functional extension to the language.

    Note this can also be done with A Lisp interpreter in ABAP. Due to LISP nature, a simpler interpreter can run complex programs. I will suggest that this version has more features than the demo report SFBE_EXAMPLE6.

    best regards,

    JNN

    (0) 
      1. Jacques Nomssi

        OK, you first have to learn ABAP LISP syntax, but in the end it is actually simpler.

        I would convert your example to this:

        ; Define fields

        (define PLAAB (ab-data “GS_MDPS-PLAAB” ))

        (define DELKZ (ab-data “GS_MDPS-DELKZ” ))

        (define LIFNR (ab-data “GS_MDPS-LIFNR” ))

        (define PLUMI (ab-data “GS_MDPS-PLUMI” ))

        ; test

        (and (= PLAAB ’02’) (= DELKZ ‘BB’) (> LIFNR ”) (= PLUMI ‘-‘))

        Assuming GS_MDPS is defined and you put this in the string variable code, you could now execute:

          DATA(response) = NEW lcl_lisp_interpreter( )->eval_source( code ).

        So it is different yes but certainly not more complex.

        regards,

        JNN

        (0) 

Leave a Reply