Hello SAS community,
I’m attempting to use a macro to add 2 new variables with content for some ids to a dataset.
Below is the code and the error message from the log.
Appreciate any help,
Maggie
%macro add_units_notes
(in=, out=,
list=);
data &out;
set ∈
length units $20. notes $200.;
select (lowcase(variable));
%let list_n = %eval(%sysfunc(countw(&list,'@')));
%do i = 1 %to &list_n %by 3;
%let name = %scan (&list,&i,'@');
%let units = %scan (&List,%eval(&i+1),'@');
%let notes = %scan (&List,%eval(&i+2),'@');
when (lowcase("&name"))
units = "&units"
notes = "¬es";
%end;
otherwise
units = ""
notes = "";
end;
run;
%mend add_units_notes;
%add_units_notes
(in=have, out=want,
list=time@minutes@@
diabp@mmHg@to the nearest 2 mmHg@
abcd@@collected on females only@);
desired output
units |
notes |
|
time |
minutes |
|
diabp |
mm Hg |
to the nearest 2 mmHg |
abcd |
collected on females only |
SAS Log
501 %add_units_notes
502 (inDsn=s1, outDsn=s2,
503 list=time@minutes@@
504 diabp@mmHg@to the nearest 2 mmHg@
505 abcd@@collected on females only@);
NOTE: Line generated by the invoked macro "ADD_UNITS_NOTES".
3 when (lowcase("&name")) units = "&units" notes =
-----
22
3 ! "¬es";
NOTE: Line generated by the invoked macro "ADD_UNITS_NOTES".
5 when (lowcase("&name")) units = "&units" notes =
-----
22
5 ! "¬es";
NOTE: Line generated by the invoked macro "ADD_UNITS_NOTES".
7 when (lowcase("&name")) units = "&units" notes =
-----
22
7 ! "¬es";
NOTE: Line generated by the invoked macro "ADD_UNITS_NOTES".
9 otherwise units = "" notes = ""; end; run;
-----
22
ERROR 22-322: Syntax error, expecting one of the following: !, !!, &, *, **, +, -, /, ;, <, <=,
<>, =, >, ><, >=, AND, EQ, GE, GT, IN, LE, LT, MAX, MIN, NE, NG, NL, NOTIN, OR, ^=,
|, ||, ~=.
NOTE: Character values have been converted to numeric values at the places given by:
When macros don't behave, first run the command
options mprint;
to turn on macro debugging tools, and then run the macro again. You will see this in the log:
when (lowcase("time")) units = "minutes" notes = "diabp" ;
This is the SAS code created by the macro processor. This code is not valid, it contains errors, so it can't run. This is an important part of using macros, your macro code must resolve to working legal valid SAS code.
Can you see what is the error here? Forgetting macros for a minute, what changes are needed to the above line of code to make it work?
when (lowcase("time")) units = "minutes" notes = "diabp" ;
notes should not equal "diabp"
the loop should go through twice, once to add units & then notes, I know the looping is where the problem is.
Can you please help me resolve it.
Thanks,
Margaret
Let's not get to loops just yet, you need to be able to write (and recognize) what is valid SAS code before any macro writing can be successful. Your macro code must produce valid SAS code. I want you to understand that, otherwise the next macro you write will run into similar errors.
So, no looping, and no macros in my question to you, what is wrong with this SAS code? how do you fix it so that it works?
when (lowcase("time")) units = "minutes" notes = "diabp" ;
Your code is syntactically wrong. Before dealing with the wrong value in the quotes, you must have code with correct SQL syntax.
So what SAS code do you want to run?
It looks like you are trying to generate a SELECT group block of SAS code.
So first write the SAS code and test it to make sure it works.
data have;
input variable :$32. ;
cards;
Time
SYSBP
DiaBP
;
data want;
set have;
length units $20 notes $200;
select (upcase(variable));
when ("TIME") do;
units = "minutes";
notes = " ";
end;
when ("DIABP") do;
units = "mm Hg";
notes = "to the nearest 2 mmHg";
end;
otherwise do;
units = " ";
notes = " ";
end;
end;
run;
proc print;
run;
OBS variable units notes
1 Time minutes
2 SYSBP
3 DiaBP mm Hg to the nearest 2 mmHg
Then you can try to create a macro that can create that code.
Wouldn't it be easier to put the data into a dataset and just merge it?
data units;
length variable $32 units $20 notes $200;
infile cards dsd truncover ;
input variable units notes;
cards4;
abcd,,collected on females only
diabp,mm Hg,to the nearest 2 mmHg
time,minutes,
;;;;
data want;
merge have(in=in1) units;
by variable;
if in1;
run;
SAS Innovate 2025 is scheduled for May 6-9 in Orlando, FL. Sign up to be first to learn about the agenda and registration!
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.