BookmarkSubscribeRSS Feed
🔒 This topic is solved and locked. Need further help from the community? Please sign in and ask a new question.
Tommer
Obsidian | Level 7

Hi,

 

New to macro programming - I am confused when to use macro functions as the code seems to work well without macro function when used with a macro variable. The code below as an example works without using %upcase as well.


%let mod=mdx;

data cars;
set sashelp.cars;
if strip(model)=upcase("&mod");
keep model ;
run;

 

Similarly, 


%let greet = Hello my name is Sam;
%let hel= %scan(&greet,1, " "); ----> works

%put &hel;

 

data hello;
greet = %scan("&greet",1, " "); --->but this doesn't. Rather it works with scan and not %scan
run;

1 ACCEPTED SOLUTION

Accepted Solutions
ballardw
Super User

Whether to use macro function or not basically depends on the purpose of the macro function.

Consider this slightly different code using both %upcase and upcase functions:

data cars;
   set sashelp.cars (obs=5);
   newmodel = %upcase(model);
   newmodel2 = upcase(model);
   keep model newmodel newmodel2;
run;

The obs=5 is just to make a small set you can inspect quickly.

Notice that none of the Newmodel values are in all upper case except for MDX that started out all upper case. This type of macro function does not see the actual value of any data step variable.

Your code worked because the macro variable &mod is resolved at compile time becoming the equivalent of:

data cars;
set sashelp.cars;
if strip(model)=upcase("mdx");
keep model ;
run;

And the upcase function will work on any literal text.

When you use

data cars;
set sashelp.cars;
if strip(model)=%upcase("&mod");
keep model ;
run;

what happens BEFORE the data step starts to execute is the &mod resolves to mdx. Then the %upcase function is applied and the code becomes:

data cars;
set sashelp.cars;
if strip(model)="MDX";
keep model ;
run;

We can demonstrate by making macro that executes all that code and will honor the MPRINT function to show code generated by a macro:

Program:

%macro example(mod=mdx);
data cars;
set sashelp.cars;
if strip(model)=%upcase("&mod");
keep model ;
run;
%mend;

options mprint;
%example
options nomprint;

Log:

MPRINT(EXAMPLE):   data cars;
MPRINT(EXAMPLE):   set sashelp.cars;
MPRINT(EXAMPLE):   if strip(model)="MDX";
MPRINT(EXAMPLE):   keep model ;
MPRINT(EXAMPLE):   run;

 

Most of the macro functions similar to data step functions such as %upcase and %scan are more intended to work with text that is creating code that needs the result, not manipulate data in data step (or most other places).

Knowing the timing of when things happens is important as we get a question nearly every week that mixes macro functions and data step code asking why something didn't work.

 

Now, go back to my first example with both %upcase and Upcase functions and determine what code what generated and see if you understand why there were no errors but also no change to the Newmodel variable.

 

 

View solution in original post

3 REPLIES 3
Tom
Super User Tom
Super User

You use the macro processor to generate code.  So replace the macro function call with its results and LOOK at the text it generated and see if it is valid SAS code or not.

Take your first example:

if strip(model)=upcase("&mod");

That will generate the SAS code:

if strip(model)=upcase("mdx");

Which looks like valid SAS code.

 

Now your second example:

greet = %scan("&greet",1, " ");

So replace &GREET you get this macro function call:

greet = %scan("Hello my name is Sam",1, " ");

Which says to use either space or double quote character as delimiter and find the first word in the string "Hello my name is Sam".  Since you didn't use the M modifier in the function call the leading delimiter " is ignored and Hello is the first word found.

So you generated this SAS statement.

greet = Hello ;

Which is valid SAS code, but probably NOT what you intended, unless your data step has a variable named HELLO.

 

You probably meant to do:

greet = "%scan(&greet,1,%str( ))";

Which will generate the statement:

greet = "Hello";

 

ballardw
Super User

Whether to use macro function or not basically depends on the purpose of the macro function.

Consider this slightly different code using both %upcase and upcase functions:

data cars;
   set sashelp.cars (obs=5);
   newmodel = %upcase(model);
   newmodel2 = upcase(model);
   keep model newmodel newmodel2;
run;

The obs=5 is just to make a small set you can inspect quickly.

Notice that none of the Newmodel values are in all upper case except for MDX that started out all upper case. This type of macro function does not see the actual value of any data step variable.

Your code worked because the macro variable &mod is resolved at compile time becoming the equivalent of:

data cars;
set sashelp.cars;
if strip(model)=upcase("mdx");
keep model ;
run;

And the upcase function will work on any literal text.

When you use

data cars;
set sashelp.cars;
if strip(model)=%upcase("&mod");
keep model ;
run;

what happens BEFORE the data step starts to execute is the &mod resolves to mdx. Then the %upcase function is applied and the code becomes:

data cars;
set sashelp.cars;
if strip(model)="MDX";
keep model ;
run;

We can demonstrate by making macro that executes all that code and will honor the MPRINT function to show code generated by a macro:

Program:

%macro example(mod=mdx);
data cars;
set sashelp.cars;
if strip(model)=%upcase("&mod");
keep model ;
run;
%mend;

options mprint;
%example
options nomprint;

Log:

MPRINT(EXAMPLE):   data cars;
MPRINT(EXAMPLE):   set sashelp.cars;
MPRINT(EXAMPLE):   if strip(model)="MDX";
MPRINT(EXAMPLE):   keep model ;
MPRINT(EXAMPLE):   run;

 

Most of the macro functions similar to data step functions such as %upcase and %scan are more intended to work with text that is creating code that needs the result, not manipulate data in data step (or most other places).

Knowing the timing of when things happens is important as we get a question nearly every week that mixes macro functions and data step code asking why something didn't work.

 

Now, go back to my first example with both %upcase and Upcase functions and determine what code what generated and see if you understand why there were no errors but also no change to the Newmodel variable.

 

 

SASKiwi
PROC Star

The important point to remember is that use of SAS macro must result in syntactically and logically correct SAS code. Your example:

%let greet = Hello my name is Sam;
data hello;
greet = %scan("&greet",1, " "); 
run;

  Will resolve to this SAS code:

data hello;
greet = hello; 
run;

HELLO doesn't exist as a variable so GREET is set to a missing value.

 

Since you want to assign the value "Hello" to GREET, all you need to do is wrap your %SCAN in double quotes:

data hello;
greet = "%scan("&greet",1, " ")"; 
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
  • 3 replies
  • 491 views
  • 3 likes
  • 4 in conversation