Reputation: 87
I have problem with simply macro %IF %ELSE. I have to set switch "Y" or "N" (more in the future) where this variable runs differents part of code. Example:
data REKORD_RACH;
input id_wsadu dept $;
datalines;
1 Sales
2 Acctng
3 eeeaa
4 ffff
;
%LET Czy_Max = 'Y'; /*<=============================== SWITCH*/
OPTION MPRINT;
option compress=yes validvarname=any;
%macro Set_id_wsadu(Czy_Max);
%if &Czy_Max. = 'N' %then
%do;
%let id_wsadu = 3;/*Tu wpisujemy ręcznie id wsadu które nas interesuje*/
%end;
%else %if &Czy_Max. = 'Y' %then
%do;
Proc SQL NOPRINT;
Select MAX(id_wsadu) Into :id_wsadu
From Work.REKORD_RACH;
quit;
%end;
%mend;
%Set_id_wsadu;
%put &id_wsadu;
PROC SQL;
CREATE TABLE REKORD_RACH_GET AS
SELECT *
FROM REKORD_RACH
WHERE ID_WSADU = &id_wsadu
;QUIT;
But Sas guide shows me these log:
54 %mend;
55 %Set_id_wsadu;
56
57 %put &id_wsadu;
WARNING: Apparent symbolic reference ID_WSADU not resolved.
&id_wsadu
What I should do to make it work?
Upvotes: 0
Views: 5724
Reputation: 51566
You are having trouble with macro variable scoping and confusion about values of macro variables.
First you defined a global macro variable (since you ran the %let
outside of any specific macro scope).
%LET Czy_Max = 'Y';
Then you defined a macro that uses the same macro variable name as a parameter.
%macro Set_id_wsadu(Czy_Max);
This will create a local macro variable named Czy_Max
that will hide the value of the global macro variable with the same name. You can make this setup work by simply passing the value of the global macro variable into the macro when you call it. Like this:
%Set_id_wsadu(&Czy_Max);
Although it might be less confusing to use different names for the global and local macro variables.
Second you are setting a value to a macro variable inside the macro without clearly defining whether SAS should treat that macro variable as local or global.
%let id_wsadu = 3;
If the macro variable id_wsadu
already existed when that assignment runs then its value will be updated. Otherwise it will cause a local macro variable to be created that will cease to exist when the macro finishes running. You could fix this by making sure to define the macro variable before calling the macro.
%let id_wsadu = ;
%Set_id_wsadu(&Czy_Max);
Or you could add a %global
statement in the macro to define the macro variable in the global symbol table before assigning it a value. But this will cause problems if you call this macro from another macro that has already created that macro variable as local. You cannot make a NEW global macro variable with the same name as an existing local macro variable. To prevent that error you can test if the macro variable already exists before making it global. Like this:
%if not %symexist(id_wsadu) %then %global id_wsadu;
Finally why are you adding quotes into the values of your macro variables? It looks like you are doing it consistently so the code should work, but it might mean that you do not understand that the quotes are actually part of the macro variables value. This is different than in SAS code where the quotes are needed so that the compiler knows the difference between a string literal, a numeric literal and a variable name or SAS keyword. So in SAS code the quotes around a literal are not part of the value.
So in a data step you could run code like this using different outer quotes and the literals would match.
if 'A' = "A" then
But in macro code the quotes are part of the value so if you tried this code:
%if 'A' = "A" %then
the two values are different since '
is not equal to "
.
Upvotes: 2
Reputation: 676
First you need add %global id_wsadu;
to your macro. This will make the macro value resolve outside the macro. Then you need to call your macro properly by passing a parameter e.g %Set_id_wsadu('Y')
. Here:
%macro Set_id_wsadu(Czy_Max);
%global id_wsadu;
%if &Czy_Max. = 'N' %then
%do;
%let id_wsadu = 3;/*Tu wpisujemy ręcznie id wsadu które nas interesuje*/
%end;
%else %if &Czy_Max. = 'Y' %then
%do;
Proc SQL NOPRINT;
Select MAX(id_wsadu) Into :id_wsadu
From Work.REKORD_RACH;
quit;
%end;
%mend;
%Set_id_wsadu('Y');
%put &id_wsadu;
PROC SQL;
CREATE TABLE REKORD_RACH_GET AS
SELECT *
FROM REKORD_RACH
WHERE ID_WSADU = &id_wsadu.;
QUIT;
Upvotes: 3