BookmarkSubscribeRSS Feed
urban58
Quartz | Level 8

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 = "&notes";

                           %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  !  "&notes";

NOTE: Line generated by the invoked macro "ADD_UNITS_NOTES".

5                 when (lowcase("&name"))                 units = "&units"                 notes =

                                                                                           -----

                                                                                           22

5  !  "&notes";

NOTE: Line generated by the invoked macro "ADD_UNITS_NOTES".

7                 when (lowcase("&name"))                 units = "&units"                 notes =

                                                                                           -----

                                                                                           22

7  !  "&notes";

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:

6 REPLIES 6
PaigeMiller
Diamond | Level 26

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?

--
Paige Miller
urban58
Quartz | Level 8
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

 

PaigeMiller
Diamond | Level 26

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" ;

 

--
Paige Miller
Tom
Super User Tom
Super User

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.

Spoiler
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.

 

 

Tom
Super User Tom
Super User

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-2024.png

Available on demand!

Missed SAS Innovate Las Vegas? Watch all the action for free! View the keynotes, general sessions and 22 breakouts on demand.

 

Register now!

How to Concatenate Values

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.

Click image to register for webinarClick image to register for webinar

Classroom Training Available!

Select SAS Training centers are offering in-person courses. View upcoming courses for:

View all other training opportunities.

Discussion stats
  • 6 replies
  • 633 views
  • 1 like
  • 4 in conversation