SAS Programming

DATA Step, Macro, Functions and more
BookmarkSubscribeRSS Feed
🔒 This topic is solved and locked. Need further help from the community? Please sign in and ask a new question.
Daniel_Paul
Obsidian | Level 7

Hello,

 

I try to define macro variables in an iterative loop. An altough the code underneath does what it should (SAS 9.4), we can expect a warning message "apparent symbolic references not resolved". Actually I have no idea how a more elegant solution might look. Can you help me?

 

%MACRO a(XVAR1=, CCENT=, GCENT=);
%MACRO NAMEP(prefix,maxnum);
	%DO i=1 %to &maxnum;
		&prefix&i
	%END;
%MEND NAMEP;


%if %sysevalf(%superq(XVAR1)=,boolean) = 0 %then %do; 
	%let NXVAR1 = 1;                             
	%do %while(%length(%scan(&XVAR1,&NXVAR1)));
		%let NXVAR1 = %EVAL(&NXVAR1 + 1);
	%end;
	%Let NXVAR1 = %eval(&NXVAR1 -1);
	%Do N1 = 1 %to &NXVAR1;
		%Let a=%scan(&XVAR1,&N1);
		%Let b=%index(&CCENT,&a);
		%Let c=%index(&GCENT,&a);
		%if &b > 0 %then %do;
			%Let X1&N1 = &a.cc;
		%end;
		%else %if &c > 0 %then %do;
			%Let X1&N1 = &a.gc;
		%end;
		%else %do;
			%Let X1&N1 = &a;
		%end;
	%end;
	%let XVAR1n = %namep(&X1,&NXVAR1);
%end;
%else %do;
	%Let XVAR1n = ;
%end;
%put &XVAR1n;

%mend a;

%a(XVAR1=xvar1a xvar1b, CCENT=xvar1b, GCENT=xvar1a);

Bye, Daniel       

1 ACCEPTED SOLUTION

Accepted Solutions
ArtC
Rhodochrosite | Level 12

First as was mentioned by @ballardw embedded macro definitions are not needed and almost always counter productive.  The macro definitions would appear as:

%MACRO NAMEP(prefix,maxnum);
	%DO i=1 %to &maxnum;
		&prefix&i
	%END;
%MEND NAMEP;
%MACRO a(XVAR1=, CCENT=, GCENT=);
%local xvar1n;
....

The better news is that you don't need the %NAMEP macro anyway.  Let's look at your other code a bit.  This portion counts the number of words in &XVAR1.

	%let NXVAR1 = 1;                             
	%do %while(%length(%scan(&XVAR1,&NXVAR1)));
		%let NXVAR1 = %EVAL(&NXVAR1 + 1);
	%end;
	%Let NXVAR1 = %eval(&NXVAR1 -1);

This is simplified with the COUNTW function.

	%let NXVAR1 = %sysfunc(countw( &XVAR1));                            

The call to the %NAMEP is causing an error (unitialized variable because &X1 is not defined).  Since you already have a loop. the definition of &XVAR1N can be moved insite the loop.

		%else %do;
			%Let X1&N1 = &a;
		%end;
	  %let XVAR1n = &xvar1n &&x1&n1;
	%end;
%end;
%else %do;
	%Let XVAR1n = ;
%end;
%put &XVAR1n;

%mend a;

Notice that &XVAR1N is initialized as a local macro variable just below the macro statement. Other cleanup in the macro is possible, but this should get you started.

View solution in original post

5 REPLIES 5
LaurieF
Barite | Level 11

I can't work out exactly what you're trying to do, but is it simply a case of:

	%let XVAR1n = %namep(X1, &NXVAR1);
RW9
Diamond | Level 26 RW9
Diamond | Level 26

What exactly is it your trying to do?  I can guarentee you thre is a far simpler and easier to maintain way of doing things thatn that, be it re-modelling your data, or using inbuilt SAS functionality.  Creating endless macro lists, macros and such like is a recipe for obfuscatd, unmaintable code which will fall over every time you run it.

ballardw
Super User

Defining a macro to include another macro, especially one such as your NAMEP that has no dependencies on the parameters of the outmacro is poor practice. As a minimum you waste compute cycles recompiling it everytime the outer macro executes.

 

And it really helps to provide an example of what you expect this macro to produce.

ArtC
Rhodochrosite | Level 12

First as was mentioned by @ballardw embedded macro definitions are not needed and almost always counter productive.  The macro definitions would appear as:

%MACRO NAMEP(prefix,maxnum);
	%DO i=1 %to &maxnum;
		&prefix&i
	%END;
%MEND NAMEP;
%MACRO a(XVAR1=, CCENT=, GCENT=);
%local xvar1n;
....

The better news is that you don't need the %NAMEP macro anyway.  Let's look at your other code a bit.  This portion counts the number of words in &XVAR1.

	%let NXVAR1 = 1;                             
	%do %while(%length(%scan(&XVAR1,&NXVAR1)));
		%let NXVAR1 = %EVAL(&NXVAR1 + 1);
	%end;
	%Let NXVAR1 = %eval(&NXVAR1 -1);

This is simplified with the COUNTW function.

	%let NXVAR1 = %sysfunc(countw( &XVAR1));                            

The call to the %NAMEP is causing an error (unitialized variable because &X1 is not defined).  Since you already have a loop. the definition of &XVAR1N can be moved insite the loop.

		%else %do;
			%Let X1&N1 = &a;
		%end;
	  %let XVAR1n = &xvar1n &&x1&n1;
	%end;
%end;
%else %do;
	%Let XVAR1n = ;
%end;
%put &XVAR1n;

%mend a;

Notice that &XVAR1N is initialized as a local macro variable just below the macro statement. Other cleanup in the macro is possible, but this should get you started.

Daniel_Paul
Obsidian | Level 7

Thank you for the valuable thoughts and the time that you have spent on my problem.

 

For the sake of completeness here the working code:

 

%MACRO a(XVAR1=, CCENT=, GCENT=);
%local xvar1n;
%if %sysevalf(%superq(XVAR1)=,boolean) = 0 %then %do; 
	%let NXVAR1 = %sysfunc(countw(&XVAR1));                             
	%Do N1 = 1 %to &NXVAR1;
		%Let a=%scan(&XVAR1,&N1);
		%Let b=%index(&CCENT,&a);
		%Let c=%index(&GCENT,&a);
		%if &b > 0 %then %do;
			%Let X1&N1 = &a.cc;
		%end;
		%else %if &c > 0 %then %do;
			%Let X1&N1 = &a.gc;
		%end;
		%else %do;
			%Let X1&N1 = &a;
		%end;
		%let XVAR1n = &XVAR1n &&X1&N1;
	%end;
%end;
%else %do;
	%Let XVAR1n = ;
%end;
%put &XVAR1n;
%mend a;

%a(XVAR1=xvar1a xvar1b, CCENT=xvar1b, GCENT=xvar1a);

sas-innovate-wordmark-2025-midnight.png

Register Today!

Join us for SAS Innovate 2025, our biggest and most exciting global event of the year, in Orlando, FL, from May 6-9. Sign up by March 14 for just $795.


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.

SAS Training: Just a Click Away

 Ready to level-up your skills? Choose your own adventure.

Browse our catalog!

Discussion stats
  • 5 replies
  • 1318 views
  • 1 like
  • 5 in conversation