## Iterative definition of macro variables

Solved
Occasional Contributor
Posts: 17

# Iterative definition of macro variables

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

Accepted Solutions
Solution
‎03-15-2017 04:01 AM
Valued Guide
Posts: 653

## Re: Iterative definition of macro variables

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.

All Replies
Super Contributor
Posts: 268

## Re: Iterative definition of macro variables

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

``	%let XVAR1n = %namep(X1, &NXVAR1);``
Super User
Posts: 9,799

## Re: Iterative definition of macro variables

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.

Super User
Posts: 13,889

## Re: Iterative definition of macro variables

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.

Solution
‎03-15-2017 04:01 AM
Valued Guide
Posts: 653

## Re: Iterative definition of macro variables

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.

Occasional Contributor
Posts: 17

## Re: Iterative definition of macro variables

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);``````
☑ This topic is solved.