How to deal with &GLOBAL-DEFINE in Non-Static values?

rrojo7229

Member
Hi,

Could you to guide me how can I built a code but applying variable values to &GLOBAL-DEFINE?
As far I understood &GLOBAL-DEFINE works in a Static concept but why this peace of code works?

/*** Works OK *****/
def var yvar as int .
def var zvar as int.
def var vdepo as int.

def var tmp-start-date as date initial 04/01/08.
def var tmp-end-date as date initial 04/30/08.

find first depot no-lock no-error.
disp depo.
assign vdepo = int(depot.depo).

&GLOBAL-DEFINE last-value vdepo

yvar = {&last-value}.
zvar = {&last-value}.

message vdepo yvar zvar.

/*** Works OK *****/

Note: the values for yvar and zvar comes with the value of vdepo. That's great.
But when I try to go forward using :

&IF ( INT({&last-value}) = vdepo )


Brings me the message: Invalid use of nonconstant elements in preprocessor expression. (2965)

/*** It does NOT work Ok ****/

FOR EACH ledger WHERE ledger.ledger-ind = "s" and
ledger.co-code = 'bwg' no-lock:

disp ledger.co-code
ledger.ledger-code.


&IF ( INT({&last-value}) = vdepo )
&THEN
FOR EACH sltran WHERE sltran.co-code = ledger.co-code
AND sltran.ledger-code = ledger.ledger-code
AND sltran.doc-date GE tmp-start-date
AND sltran.doc-date LE tmp-end-date NO-LOCK
USE-INDEX doc-date:

message "first for each".
pause.

&ELSE

FOR EACH sltran WHERE sltran.co-code = ledger.co-code
AND sltran.ledger-code = ledger.ledger-code
AND sltran.entry-date GE tmp-start-date
AND sltran.entry-date LE tmp-end-date NO-LOCK
USE-INDEX entry-date1 :

message "second for each".
pause.

&ENDIF

END.

/*** It does NOT work Ok ****/

Although the message:
Brings me the message: Invalid use of nonconstant elements in preprocessor expression. (2965)

is a warning message, the second piece is ignored...

This is needed because I want to make different conditions and indexes for for each depending of variable vdepo.

Thanks in advance,
Regards,
 
The thing to understand here is that your &GLOBAL and &IF statements are preprocessors, and are evaluated/expanded out at compile-time. So, in your first example:

----------------------

&GLOBAL-DEFINE last-value vdepo

yvar = {&last-value}.
zvar = {&last-value}.

message vdepo yvar zvar.

----------------------

will be compiled into r-code as:

----------------------

&GLOBAL-DEFINE last-value vdepo

yvar = vdepo.
zvar = vdepo.

message vdepo yvar zvar.

----------------------

So, as you can see, the &GLOBALs result in text substitution of the variable name vdepo. Although this works fine, I'm not really sure what good it does you, and I think there's no need for a &GLOBAL in this kind of circumstance.

In your next example, you're now using &IF. This basically means:

&IF something &THEN
----use this section of code when you compile
&ELSE
----use this other section of code when you compile

So, when you say:

-----------------------
&IF ( INT({&last-value}) = vdepo )
&THEN
-----------------------

the compiler looks at the statement, and realises that it doesn't know the value of vdepo at this time (you're only compiling, the system isn't running), and so can't ever evaluate the result of the &IF. That's why you get the warning.

So, the answer is that you shouldn't use &IF for this, because you're trying to use a value that can only be determined at run-time to instruct the compiler at compile-time. If you want to see how &IF and other preprocessors expand out, you can use the COMPILE statement with the LISTING parameter to get a text file showing the end result of the source code (and therefore what ends up in the r-code).

The solution is to use a regular IF statement (if you're stuck on static queries), or use a dynamic query to build up the where clause at run-time.
 
Hi ,

Could you give a help how can I do that using Dinamic Queries?

I know that should work for "where" clausule but Does it works for different indexes, too?

1)
FOR EACH sltran WHERE sltran.co-code = ledger.co-code
AND sltran.ledger-code = ledger.ledger-code
AND sltran.doc-date GE tmp-start-date
AND sltran.doc-date LE tmp-end-date NO-LOCK
USE-INDEX doc-date:

2)
FOR EACH sltran WHERE sltran.co-code = ledger.co-code
AND sltran.ledger-code = ledger.ledger-code
AND sltran.entry-date GE tmp-start-date
AND sltran.entry-date LE tmp-end-date NO-LOCK
USE-INDEX entry-date1 :


Thanks in advance,
Kind regards,
 
Absolutely no problem selecting an index in a dynamic query. Taking one of your examples:

Code:
DEFINE VARIABLE hQuery AS HANDLE      NO-UNDO.
DEFINE VARIABLE cWhere AS CHARACTER   NO-UNDO.
 
    cWhere = "FOR EACH sltran NO-LOCK WHERE sltran.co-code      = " + QUOTER(ledger.co-code)
                                 + "    AND sltran.ledger-code  = " + QUOTER(ledger.ledger-code)
                                 + "    AND sltran.doc-date    GE " + STRING(tmp-start-date)
                                 + "    AND sltran.doc-date    LE " + STRING(tmp-end-date)
                                 + "  USE-INDEX doc-date".
 
    CREATE QUERY hQuery.
    hQuery:ADD-BUFFER(BUFFER sltran:HANDLE).
    hQuery:QUERY-PREPARE(cWhere).
    hQuery:QUERY-OPEN().
    hQuery:GET-FIRST(NO-LOCK).
 
    DO WHILE NOT hQuery:QUERY-OFF-END:
 
        /* do your FOR EACH block stuff */
 
        hQuery:GET-NEXT(NO-LOCK).
    END.
 
    hQuery:QUERY-CLOSE.
    DELETE OBJECT hQuery.

By stuffing the where clause into the cWhere variable, you're able to fiddle with it at your leisure, so you could use a different index in there if you wanted to.

Note that I've guessed that the ledger.co-code and ledger.ledger-code fields are character data-type, hence the use of the QUOTER function. YMMV!
 
Hi Andrew,

That works great....

You have saved a coleague from Ireland, Dublin...

Thank you very much... Good Stuff.

Kind regards,
 
Back
Top