DATA Step, Macro, Functions and more

Masking %if in macro call

Reply
Occasional Contributor
Posts: 6

Masking %if in macro call

I am trying to execute a macro code that passes a parameter with value of a conditional statement. I must not be masking it properly because SAS is giving an error that %IF statement is not valid in open code. Here is what I am trying to do:

%macro test(where);
%if %length(&where) ne 0 %then %let where1 = (where = (%unquote(&where)));
data new;
set old&where1;
run;

proc print data=new;
run;
%mend test;

%let vendorType='ACT';
Data old;
CO='EMP';bdate='24nov1972'd;mrn='1111111';output;
run;

%test(where=%bquote("%if &vendorType = EMP %then CO='EMP'; %else CO='000';"))

Appreciate the help or feedback!
SAS Super FREQ
Posts: 8,862

Re: Masking %if in macro call

Posted in reply to merrittsas
Hi:
What is the syntactically correct (working) code that you want to have generated for the compiler:

[pre]
set old(where=(CO='EMP'));

or

set old(where=(CO='000'));

or

set old(where=(%if &vendorType=EMP %then CO='EMP'; %else CO='000'Smiley Wink);
[/pre]

What does your working program look like? If all you want to do is a PROC PRINT, then there's no need to create data set NEW. You could just do a PROC PRINT on data set OLD with a WHERE clause applied.

I don't understand the need to send the %IF statement via a macro parameter, so that's where I'm having a problem. You can keep all your macro logic in the macro program and just change the values needed for the SET or the PROC PRINT accordingly.

cynthia
Occasional Contributor
Posts: 6

Re: Masking %if in macro call

Posted in reply to Cynthia_sas
the result I would like to have is:
set old(where=(%if &vendorType=EMP %then CO='EMP'; %else CO='000'Smiley Wink);

I am trying to use an existing macro that has a Where parameter and uses the following statements in the macro:
%if %length(&where) ne 0 %then %let where = (where = (&where));
%let dsid = %sysfunc(open(&data&where));

I was just trying to test on how to pass a conditional %if %then%else statement in the WHERE parameter in a macro call.
SAS Super FREQ
Posts: 8,862

Re: Masking %if in macro call

Posted in reply to merrittsas
Hi:
There is a difference between where and when the %SYSFUNC function with OPEN is resolved and executed and trying to use a %IF in your macro program invocation. The invocation is happening in open code. I don't think there's any quoting function you can use that will mask %IF in the invocation itself.

In your %SYSFUNC example, the &data&where is resolved to something like this, internally, by the macro processor and -THEN- the %SYSFUNC does the work:

%let dsid2=%sysfunc(open(work.old(where=(CO="EMP")),i));

when you switch to a set statement, then you need to generate a statement like one of these to go to the compiler:

set work.old(where=(CO="EMP")); or
set work.old(where=(CO="000"));

By the time the %SYSFUNC hits the syntax compiler, all references to %IF are gone. That is also what must happen with your SET statement. By the time it hits the compiler, all the %IF references must be resolved to syntactically correct code.

The older program that you are trying to modify (from DSID method to SET method) may have to be changed if you want to conditionally set the value of the WHERE statement or clause based on a macro variable. The place to do that might not be in the macro invocation statement, but in the macro program, where %IF is allowed and will be resolved before any other statements get sent to the compiler. Also, you might want to reconsider how you assign a value to the where clause and move to different logic.

How is &WHERE being used as a parameter, currently? In the program that works?? What does the program look like where the DSID method is used? How does &WHERE get assigned a value in that macro invocation??? It probably looks something like this:

%mycall(where=%str(co='EMP'));
or
%mycall(where=co='EMP');

cynthia
Super Contributor
Posts: 359

Re: Masking %if in macro call

Posted in reply to Cynthia_sas
Try using a non macro where clause instead:

("&vendorType" = "EMP" and CO = 'EMP') or ("&vendorType" ne "EMP" and CO = '000')

That way you are not getting out of sync with the macro processor.
Ask a Question
Discussion stats
  • 4 replies
  • 177 views
  • 0 likes
  • 3 in conversation