Application Development Discussions
Join the discussions or start your own on all things application development, including tools and APIs, programming models, and keeping your skills sharp.
cancel
Showing results for 
Search instead for 
Did you mean: 

Dynamic Logical Expressions in ABAP: IF (lt_cond)...

Former Member
0 Kudos

is it possible to have a dynamically constructured logical expression?

I have a condition I need to use in an IF, but I want to avoid hard-coding, so I dynamicallybuild it.

for a simple example:

CONCATENATE ITAB-f1
           'EQ'
           varValue
           INTO lt_cond SEPARATED BY SPACE.
IF (lt_cond).
  WRITE:/ 'Success'.
ENDIF.

Is it possible to do this?

NL

15 REPLIES 15

sergey_korolev
Active Contributor
0 Kudos

I'm afraind there is no dynamic conditions in IF. There is a statement GENERATE SUBROUTINE POOL. By the way, are you doing some HR programming?

Message was edited by: Sergei Korolev

Problems with my mentality.. Sorry for hasty and stupid answer.. Certainly RANGES, SELECT-OPTIONS

Message was edited by: Sergei Korolev

Former Member
0 Kudos

Try this piece of code....

<b>DATA: t_t001 TYPE t001 OCCURS 0 WITH HEADER LINE.

DEFINE my_dynamic_check.

if &1 &2 &3.

write:/ 'Success'.

else.

write:/ 'Failed'.

endif.

END-OF-DEFINITION.

SELECT * FROM t001 INTO TABLE t_t001.

LOOP AT t_t001.

my_dynamic_check t_t001-bukrs eq 'US01'. <u>"US01 can be replaced by a company code in table T001</u>

ENDLOOP.</b>

0 Kudos

You may also be able use a range.

ranges: r_datum for sy-datum.

r_datum-sign = 'I'.
r_datum-option = 'EQ'.
r_datum-low = sy-datum.
apppend r_datum.

If sy-datum in r_datum.

Endif.

Regards,

Rich Heilman

0 Kudos

Rishi,

Is there any documentation I can read up on that you know of for this?

I'm not sure what the <b>&1 &2 &3</b> do or what they are.

They must represent some kind of condition.

-Natasha

0 Kudos

Look at the documentation for DEFINE. (in the abap editor select DEFINE and hit <b>F1</b>)

&1 &2 &3 are placepolders and are expanded when the macro is executed.

Rishi

0 Kudos

Hi Natasha

What Rishi recommended is a good way to solve your requirement. With <b>DEFINE</b> statement you define macros (i.e. inline functions). Macros are not subroutines, they just help simplifying code view and this kind of jobs and during activation the code of the macro is inserted at the place it is called. We use <i>&1,...,&7</i> (you can use up to 7 arguements) to substitute arguements of macros respectively. Think that the code within a <b>"DEFINE...END-OF-DEFINITION"</b> block will be inserted in the place where macro is called and the arguements when you call are inserted in places.

As an alternative but some more complicated way is to generate dynamic subroutine pools. You can get help on this via the F1 help for the statement <b>"GENERATE SUBROUTINE-POOL..."</b>.

Regards

*--Serdar <a href="https://www.sdn.sap.com:443http://www.sdn.sap.comhttp://www.sdn.sap.com/irj/servlet/prt/portal/prtroot/com.sap.sdn.businesscard.sdnbusinesscard?u=qbk%2bsag%2bjiw%3d">[ BC ]</a>

0 Kudos

I am trying to use the macro to check an IF (cond).

cond is a dynamically constructed condition.

The bold part of my code way below is my problem area.

I'm having no trouble getting COND constructed. But I am having trouble between my macro and the processing as my error always tells me I'm calling my macro without 2 actual parameters. Or when I DEFINE my macro with &1 instead of &1 &2, I get 'incorrect logical expression'.

I've read all the documentation I can find on this, but i still cannot figure out why my macro is not processing.

Code is lengthy, but if you can, please help.

I'm anticipating the output to be 'FAILURE' at this point. I just want the condition COND to be processed.

data: tabfield(20) type c,
      orcheck type I,
      cond type string.
DATA: BEGIN OF ITAB_NOTIDX OCCURS 0,
      FIELD LIKE ZDOLTARC02-SEARCHFLD,
      VALUE LIKE ZDOLTARC03-VALUE,
      STRUCTURE LIKE ZDOLTARC02-STRUCTURE,
      AOBJ LIKE ZDOLTARC02-A_OBJ,
      END OF ITAB_NOTIDX.
DATA: BEGIN OF ITAB_AOBJ OCCURS 0,
      AOBJ LIKE ZDOLTARC02-A_OBJ,
      END OF ITAB_AOBJ.
DATA: ITAB_AOBJF LIKE ITAB_AOBJ.
DATA: ITAB_NOTIDXF LIKE ITAB_NOTIDX.
DATA: varAOBJ LIKE ZDOLTARC02-A_OBJ.
      
ITAB_NOTIDXF-FIELD = 'LIFNR'.
ITAB_NOTIDXF-VALUE = '123'.
ITAB_NOTIDXF-STRUCTURE = 'BKPF'.
ITAB_NOTIDXF-AOBJ = 'FI_DOCUMNT'.
APPEND ITAB_NOTIDXF TO ITAB_NOTIDX.
ITAB_NOTIDXF-FIELD = 'LIFNR'.
ITAB_NOTIDXF-VALUE = 'ABC'.
ITAB_NOTIDXF-STRUCTURE = 'BKPF'.
ITAB_NOTIDXF-AOBJ = 'FI_DOCUMNT'.
APPEND ITAB_NOTIDXF TO ITAB_NOTIDX.
ITAB_NOTIDXF-FIELD = 'LIFNR'.
ITAB_NOTIDXF-VALUE = '001'.
ITAB_NOTIDXF-STRUCTURE = 'BKPF'.
ITAB_NOTIDXF-AOBJ = 'FI_DOCUMNT'.
APPEND ITAB_NOTIDXF TO ITAB_NOTIDX.
ITAB_NOTIDXF-FIELD = 'SAKNR'.
ITAB_NOTIDXF-VALUE = '111'.
ITAB_NOTIDXF-STRUCTURE = 'BSEG'.
ITAB_NOTIDXF-AOBJ = 'FI_DOCUMNT'.
APPEND ITAB_NOTIDXF TO ITAB_NOTIDX.
ITAB_NOTIDXF-FIELD = 'SAKNR'.
ITAB_NOTIDXF-VALUE = '222'.
ITAB_NOTIDXF-STRUCTURE = 'BSEG'.
ITAB_NOTIDXF-AOBJ = 'FI_DOCUMNT'.
APPEND ITAB_NOTIDXF TO ITAB_NOTIDX.
ITAB_NOTIDXF-FIELD = 'KUNNR'.
ITAB_NOTIDXF-VALUE = 'CCC'.
ITAB_NOTIDXF-STRUCTURE = 'BSEG'.
ITAB_NOTIDXF-AOBJ = 'FI_DOCUMNT'.
APPEND ITAB_NOTIDXF TO ITAB_NOTIDX.
ITAB_NOTIDXF-FIELD = 'KUNNR'.
ITAB_NOTIDXF-VALUE = 'DDD'.
ITAB_NOTIDXF-STRUCTURE = 'BSEG'.
ITAB_NOTIDXF-AOBJ = 'FI_DOCUMNT'.
APPEND ITAB_NOTIDXF TO ITAB_NOTIDX.

LOOP AT ITAB_NOTIDX.
  WRITE:/ ITAB_NOTIDX-FIELD, ITAB_NOTIDX-VALUE, ITAB_NOTIDX-STRUCTURE, ITAB_NOTIDX-AOBJ.
ENDLOOP.

DATA: VARFIELDNAME LIKE ZDOLTARC02-FIELD.
CONCATENATE cond
           '('
           INTO Cond.
SORT ITAB_NOTIDX BY AOBJ FIELD.
varFieldName = Itab_NOTIDX-FIELD.


ORCHECK = 0.
ITAB_AOBJF = 'FI_DOCUMNT'.
APPEND ITAB_AOBJF TO ITAB_AOBJ.
LOOP AT ITAB_AOBJ.
   MOVE ITAB_AOBJ-AOBJ TO varAOBJ.
   WRITE:/ varAOBJ.
   LOOP AT ITAB_NOTIDX WHERE AOBJ EQ varAOBJ.
     	 WRITE:/ 'LOOP TEST'.
        IF ITAB_NOTIDX-FIELD EQ varFieldName.
             WRITE:/ VARFIELDNAME.
             IF ORCHECK <> 0.
 		   CONCATENATE cond
                	       'OR'
                       	INTO cond SEPARATED BY SPACE.
             ENDIF.
             CONCATENATE ITAB_NOTIDX-STRUCTURE
                    '-'
                    ITAB_NOTIDX-FIELD
                    INTO tabfield.
             CONCATENATE cond
                    tabfield
                    'EQ'
                    '''' ITAB_NOTIDX-value ''''
                    INTO cond SEPARATED BY SPACE.
             ORCHECK = ORCHECK + 1.
        ELSE.
            MOVE ITAB_NOTIDX-FIELD TO varFieldName.
	     WRITE:/ '2', VARFIELDNAME.
            CLEAR TABFIELD.
	     ORCHECK = 0.
	     CONCATENATE ITAB_NOTIDX-STRUCTURE
		         '-'
			 varFieldName
			 INTO TABFIELD.
 		
             CONCATENATE cond
                    ')'
                    'AND'
                    '('
                    TABFIELD
		      'EQ'
		      '''' ITAB_NOTIDX-VALUE ''''
                    INTO cond SEPARATED BY SPACE.
      	     ORCHECK = ORCHECK + 1.
        ENDIF.
   ENDLOOP.
ENDLOOP.
CONCATENATE COND
            ')'
            INTO COND.

write:/ COND. "constructed properly
<b>DEFINE my_dynamic_check.
if &1, &2.
  write:/ 'Success'.
else.
  write:/ 'Failed'.
endif.
END-OF-DEFINITION.
my_dynamic_check (cond).</b>

0 Kudos

You are only passing in one placeholder to your macro. Try this instead:

DEFINE my_dynamic_check.
  if &1.  
    write:/ 'Success'.
  else.  
    write:/ 'Failed'.
  endif.
END-OF-DEFINITION.
my_dynamic_check cond.

There might also be a problem if your &1 placeholder is replaced with something that causes the line size to exceed 72. Try this with a short one first to make sure it works, then try it with a long one.

Let us know how it goes.

Message was edited by: Charles Folwell

0 Kudos

My cond line size is definitely larger than 72. So this could be a problem.

I did try to pass just one placeholder to my macro, but whenever I do that I get the 'Incorrect Logical Expression'.

I tried a shorter cond of something simple like cond = 'CHECK EQ OCHECK' where I assigned value of 0 to both check and ocheck, but I still get this error.

By the way, thanks for helping.

0 Kudos

Now that I think about this some more. I do not think this is going to work. Macros are resolved at generate time, i.e. compile time. So when your program is generated, your reference to the macro is turned into code. Since you do not decide a value for cond until execution time, the value is not available when the macro is converted into code.

The macro invocation also does NOT resolve variables. So if you code

my_dynamic_check cond.

You will get

IF cond.

as code which is not syntactically correct.

I do not think macros support resolution via (cond).

I think you will need to go with the RANGES option or the GENERATE SUBROUTINE... option.

0 Kudos

As already stated -there is not much dynmaic behind macros - but here goes a completly dfferent idea - isnt there a class (in recent releases) with which you can create javascript? (cl_java_script?).

Regarding performance and complexity I am not sure if I wuld follow an approach but maybe a nice way if nothing else helps.

Christian

0 Kudos

Thanks Christian, I found some documentation and examples of javascripts in ABAP programs. I'm going to try some code out, but first I want to ask you something:

Are you suggesting that I dynamically populate the condition and then test the 'IF cond' within the script?

Or can I keep the dynamically constructed condition in ABAP and just do an <b>IF cond</b> in javascript?

My fingers are crossed that you suggest the latter.

0 Kudos

Hi Natasha

Why are you going into javascript? You can generate dynamic subroutine pools in ABAP. Just inspect the F1 help for the statement <b>"GENERATE"</b>.

Regards

*--Serdar <a href="https://www.sdn.sap.com:443http://www.sdn.sap.comhttp://www.sdn.sap.com/irj/servlet/prt/portal/prtroot/com.sap.sdn.businesscard.sdnbusinesscard?u=qbk%2bsag%2bjiw%3d">[ BC ]</a>

0 Kudos

Actually I would not recommend it at all - because I am pretty sure it means more overhead than the benefit would be worth.

To be honest, my suggestion was not the first one (because I do not know if javascript could handle IF COND and you have to bind the abap variables somehow). My knowledge of javascript is very limited but if there is a statement which can handle a dynamic if clause then you should both get working.

The advantage (if any) is that you (hopefully) do not run in the same problems as with generate subroutine.

Christian

0 Kudos

Hi Natasha

In fact, try this if you have no other options. Below I write a snippet of code. But I wrote it here and did not check in a system. Try optimizing and revising it if neccessary.


...
DATA: BEGIN OF gt_code OCCURS 0 ,
        line(72) TYPE c ,
      END OF gt_code .
DATA gv_fieldname(30) TYPE c .
FIELD-SYMBOLS: <f1>, <f2> .

REFRESH gt_code .

gt_code-line = 'REPORT ZTEST.'
APPEND gt_code .
gt_code-line = 'FORM test_conditions CHANGING ep_subrc TYPE flag .' .
APPEND gt_code .
gt_code-line = 'IF' .
APPEND gt_code .
gt_code-line = '(' .
APPEND gt_code .


*----- Begin of Procedure A
*--Generate field name for the first operand here
*--e.g. concatenate structure '-' field into gv_fieldname.

ASSIGN (gv_fieldname) TO <f1> . 

*--Generate field name for the second operand here
*--e.g. concatenate structure '-' field into
gv_fieldname.

ASSIGN (gv_fieldname) TO <f2> . 

CONCATENATE <f1> '>' <f2> 
            INTO gt_code-line
            SEPARATED BY space .
APPEND gt_code .
*----- End of Procedure A


*--For additional conditions repeat the procedure A
*--adding an operator and required paranthesises .
*--e.g. 'AND' here

gt_code-line = 'AND' .
APPEND gt_code .

*-- Insert Procedure A if needed.

*--End you if statement with a full stop
gt_code-line = ') .' .
APPEND gt_code .

ep_subrc = 'X' .

gt_code-line = 'ELSE .' .
APPEND gt_code .

gt_code-line = 'CLEAR ep_subrc .' .
APPEND gt_code .
             
gt_code-line = 'ENDIF .' .
APPEND gt_code .

gt_code-line = 'ENDFORM .' .
APPEND gt_code .


*--Now let us generate thesubroutine-pool
GENERATE SUBROUTINE POOL gt_code 
                         NAME gv_temp_prog_name .

PERFORM test_conditions IN PROGRAM gv_temp_prog_name
        CHANGING gv_passed .

*--Now you have the flag indicating whether your 
*--condition is met or not

Hope this helps...

*--Serdar <a href="https://www.sdn.sap.com:443http://www.sdn.sap.comhttp://www.sdn.sap.com/irj/servlet/prt/portal/prtroot/com.sap.sdn.businesscard.sdnbusinesscard?u=qbk%2bsag%2bjiw%3d">[ BC ]</a>