DATA Step, Macro, Functions and more

Macro syntax error %SCAN used in %DO loop

Accepted Solution Solved
Reply
Contributor
Posts: 44
Accepted Solution

Macro syntax error %SCAN used in %DO loop

I have some code that I need to put in a DO LOOP. My code works perfectly outside the loop, but I can't seem to make it work inside it.

What it does is that it takes a global macro variable that has some numbers in them and extracts one number at a time, using that to do calculations:

%LET N=5;
/* example of macro var Price = 1000 1200 1300 5000 4500 */

%MACRO RED();
	%DO j=1 %TO &N.;
		DATA Client;
			SET Client;
			Red=%SCAN(&Price.,&j.+1," ");
			IF Red-Cost>0 THEN OUTPUT;
		RUN;			
	%END;
%MEND;
%RED()

I tried a different version of the Scan function, but it doesn't work:  

Red=%SCAN(&Price.,%eval(&j.+1)," "); 

 


Accepted Solutions
Solution
‎07-26-2016 08:07 AM
Super User
Posts: 5,499

Re: Macro syntax error %SCAN used in %DO loop

Technically, " " is incorrect within a %SCAN function ... unless you want both quotes and blanks to be delimiters.  But that wouldn't cause a problem in this particular case.  The better delimiter would be %str( )

 

One problem is using &j.+1 instead of &j.  When &J=5, the %SCAN function returns no characters (because &PRICE only contains 5 words) and your DATA step statement becomes:

 

Red= ;

 

Is that the only problem you are encountering?

View solution in original post


All Replies
Super User
Posts: 19,778

Re: Macro syntax error %SCAN used in %DO loop

Your in a data step, you can use SCAN, you don't need the macro version. 

 

Also, what does &Price resolve to, and does that make sense within the comcept of a data step. Ie Is if a list or a variable? 

Contributor
Posts: 44

Re: Macro syntax error %SCAN used in %DO loop

Actually, if I put SCAN instead of %SCAN I get another type of error: "Expecting an arithmetic operator".
&Price is a global variable that stores all the possible prices for an item. I use it to compare it to a column in my dataset. If the difference is positive I need to flag it and output everything up until that point into a different dataset (RedData), then remove all these rows from the Client dataset and begin all over again until there are no more rows for that client
Super User
Posts: 7,769

Re: Macro syntax error %SCAN used in %DO loop

[ Edited ]

Elle wrote:
Actually, if I put SCAN instead of %SCAN I get another type of error: "Expecting an arithmetic operator".
&Price is a global variable that stores all the possible prices for an item. I use it to compare it to a column in my dataset. If the difference is positive I need to flag it and output everything up until that point into a different dataset (RedData), then remove all these rows from the Client dataset and begin all over again until there are no more rows for that client

%scan is a macro function; since macro language only knows the datatype text, quotes are not necessary (they even are wrongly used and cause problems in many cases). So you can use &price. as such

scan, OTOH, is a data step function, and needs a variable of type char or a string literal as its first parameter, so you have to use &price as a literal with quotes:

scan("&price.",&j.,' ')

In your case, I'd prefer to use %scan. Why? Because the substring extraction is performed once by the macro engine before the data step is compiled, while the data step function would be executed in each data step iteration when the step is executed. Therefore %scan is better performancewise.

PS and since red is meant to be a numeric variable, you would need

red = input(scan("&price.",&j.,' '),best.);

to make it so.

---------------------------------------------------------------------------------------------
Maxims of Maximally Efficient SAS Programmers
Solution
‎07-26-2016 08:07 AM
Super User
Posts: 5,499

Re: Macro syntax error %SCAN used in %DO loop

Technically, " " is incorrect within a %SCAN function ... unless you want both quotes and blanks to be delimiters.  But that wouldn't cause a problem in this particular case.  The better delimiter would be %str( )

 

One problem is using &j.+1 instead of &j.  When &J=5, the %SCAN function returns no characters (because &PRICE only contains 5 words) and your DATA step statement becomes:

 

Red= ;

 

Is that the only problem you are encountering?

Contributor
Posts: 44

Re: Macro syntax error %SCAN used in %DO loop

Posted in reply to Astounding
Thank you for your suggestion. I'm a bit afraid to use macro functions inside macro functions because I don't master them enough and instead of concentrating on the data I'm losing time trying to debug my program. When I saw this version of SCAN I thought if it works it's good enough, but thank you for your advice. I'll use it next time.And thank you for making me understand where the error came from. I thought it was weird my dataset was actually being created with that error in the log, but now I get it. I've got no more problems with the code, as crazy as that sounds. Thank you Smiley Happy
Super User
Posts: 7,769

Re: Macro syntax error %SCAN used in %DO loop

When &j = 5, your %scan tries to look for word 5+1, which is not there and therefore the %scan function call returns an emtpy string, causing a syntax error. (see log!!)

You also use the same dataset name in the data and set statements, causing permanent overwrites during the macro loop iteration.

Try this instead:

data client;
input id $ cost;
cards;
a 900
b 1100
c 1400
d 4600
e 5100
;
run;

%let price=1000 1200 1300 5000 4500;

%macro red;
	%do j = 1 %to %sysfunc(countw(&price.,' '));
		data client&j.;
			set client;
			red=%scan(&price.,&j.," ");
			if red - cost > 0 then output;
		run;			
	%end;
%mend;
%red
---------------------------------------------------------------------------------------------
Maxims of Maximally Efficient SAS Programmers
Contributor
Posts: 44

Re: Macro syntax error %SCAN used in %DO loop

Posted in reply to KurtBremser
Thank you for the suggestion. I've solved the problem now. Also, the overwriting of the table was supposed to happen because I eliminate rows if they meet a certain condition and re-start the analysis on the remaining ones until there are no more left. Thank you very much.
☑ This topic is solved.

Need further help from the community? Please ask a new question.

Discussion stats
  • 7 replies
  • 383 views
  • 5 likes
  • 4 in conversation