I have a dataset that looks like this:
DXCODE NUMBER
78060 1
7784 2
09989 3
I am trying to create 3 global macro variables called "macrovariable1", "macrovariable2", and "macrovariable3", which have the DXCODE values "78060", "7784", and "09989", respectively.
Here is my macro:
%macro macrovariables;
%do i=1 %to 3;
data _null_;
set codes;
where number = &i;
call symput('macrovariable' || trim(left(&i)), '"' || trim(left(dxcode)) || '"');
run;
%end;
%mend macrovariables;
I want this macro to replicate the following code:
data _null_;
set codes;
where number = 1;
call symput('macrovariable1', "78060");
run;
data _null_;
set codes;
where number = 1;
call symput('macrovariable1', "78060");
run;
data _null_;
set codes;
where number = 2;
call symput('macrovariable2', "7784");
run;
data _null_;
set codes;
where number = 3;
call symput('macrovariable3', "09989");
run;
Unfortunately, this code does not generate the global macro variables that I want. What am I doing wrong? Thanks.
Chuakp,
If you look in my log, my code produced three local macro variables. If you need the macro variables to be global, then simply add a statement to define them as such "%global Macrovariable&i." immediately after the do i=1 to 3 statement. It worked for me.
It looks like your problem lies in the first argument to CALL SYMPUT. Part of that would look like this on the third iteration:
trim(left(3))
You would expect the DATA step to complain that it can't apply the LEFT function to the number 3, it can only apply it to a character string. Try a simpler version for the first argument that uses double quotes instead of single:
call symput("macrovariable&i", ...
That should take care of the problem.
Thanks for the suggestion. I changed the code to:
call symput("macrovariable&i", '"' || trim(left(dxcode)) || '"');
I am still not getting this to work despite the change, unfortunately.
Chuakp,
Try this:
%macro macrovariables;
%do i=1 %to 3;
%let mv = macrovariable;
data _null_;
set codes;
where number = &i.;
call symput("macrovariable&i.",trim(left(dxcode)));
run;
%end;
%mend macrovariables;
180 %macro macrovariables;
181
182 %do i=1 %to 3;
183 %let mv = macrovariable;
184 data _null_;
185 set codes;
186 where number = &i.;
187 call symput("macrovariable&i.",trim(left(dxcode)));
188 run;
189 %put "macrovariable&i. = &&&mv.&i.";
190 %end;
191
192 %mend macrovariables;
193
194 %macrovariables;
NOTE: There were 1 observations read from the data set WORK.CODES.
WHERE number=1;
NOTE: DATA statement used (Total process time):
real time 0.00 seconds
cpu time 0.00 seconds
"macrovariable1 = 78060"
NOTE: There were 1 observations read from the data set WORK.CODES.
WHERE number=2;
NOTE: DATA statement used (Total process time):
real time 0.00 seconds
cpu time 0.00 seconds
"macrovariable2 = 7784"
NOTE: There were 1 observations read from the data set WORK.CODES.
WHERE number=3;
NOTE: DATA statement used (Total process time):
real time 0.00 seconds
cpu time 0.00 seconds
"macrovariable3 = 09989"
Thanks jwillis - unfortunately, that code does not quite get me where I need to be. I am able to get the same SAS log output as you pasted above, but this code does not result in the creation of three global macro variables (macrovariable1-macrovariable3).
Chuakp,
If you look in my log, my code produced three local macro variables. If you need the macro variables to be global, then simply add a statement to define them as such "%global Macrovariable&i." immediately after the do i=1 to 3 statement. It worked for me.
Thanks! This worked.
Using your code, I've been able to set global macro variables (where macrovariable1 = 78060, macrovariable2 = 7784, etc.). I'm trying to figure out the right way to reference these macro variables in a %do loop.
%macro admissiondx;
%do j=1 %to 100;
data codes;
if admit_dx = "¯ovariable&j." then flag = 1; /*I want this to read: if admit_dx = "78060" then flag = 1;*/
if flag > 0 then output;
drop flag;
run;
%end;
%mend admissiondx;
When I run the above code, I get a warning from SAS: "WARNING: Apparent invocation of macro MACROVARIABLE1 not resolved." I feel like there's some small change in syntax that I need to make but can't figure it out. Do you have any ideas? Thanks in advance - you've been really helpful and I appreciate it.
Chuakp,
1. Add this anywhere in your code before #2.
%let mv = macrovariable;
2. Change this: if admit_dx = "¯ovariable&j." to this: if admit_dx = "&&&mv.&j."
3. Test #2 with this anywhere after #2.
%put "macrovariable&j. = &&&mv.&j.";
Sounds like it would be better to make a format than a series of macro variables.
You don't need the macro loop and WHERE to create a macro variable from each observation of DXCODE data. Also use SYMPUTX to make the variable global if that's what you need.
Thanks for the tip.
Registration is now open for SAS Innovate 2025 , our biggest and most exciting global event of the year! Join us in Orlando, FL, May 6-9.
Sign up by Dec. 31 to get the 2024 rate of just $495.
Register now!
Learn how use the CAT functions in SAS to join values from multiple variables into a single value.
Find more tutorials on the SAS Users YouTube channel.
Ready to level-up your skills? Choose your own adventure.