03-29-2005 8:58 PM
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
03-29-2005 9:16 PM
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
03-29-2005 9:16 PM
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>
03-29-2005 9:31 PM
03-29-2005 9:58 PM
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
03-29-2005 10:07 PM
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
03-29-2005 10:47 PM
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>
03-30-2005 5:40 PM
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>
03-30-2005 6:09 PM
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
03-30-2005 6:22 PM
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.
03-30-2005 6:24 PM
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.
03-30-2005 7:20 PM
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
03-30-2005 7:43 PM
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.
03-31-2005 11:08 AM
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>
04-01-2005 12:48 PM
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
04-01-2005 7:00 PM
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>