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

I'm on Win7 Pro release 9.4 TS1M4

I would like to code below to produce:

exp_m_EL_unempl_down20

but I can't see to get the nested Unempl_perc1 macro variable to resolve.

Any suggestions are welcome.  Thank you.  -- George Rezek

code:

 

data _null_ ;

call symput('invar1','unempl') ;

call symput('product1','1st_mtg') ;

call symput('unempl_perc1','_down20') ;

call symput('gvar1','exp_m_EL') ;

run ;

%macro fuss ;

%do i = 1 %to 1 ; %put "stick1 &&invar&i.." ;

*loop through the products ;

%do j = 1 %to 1 ; %put "stick2 &&product&j.." ;

*loop through the graph variables ;

%do k = 1 %to 1 ; %put "stick3 &&gvar&k.." ;

%put "&&invar&i.._perc1 &invar1. &unempl_perc1." ;

%put "&&&gvar&k.._&&&&invar&i.._perc1. ";

%end ;%end ;%end ;run ;%mend fuss ;run;

%fuss ;

run;

 

log:

 

1104

1105 data _null_ ;

1106 call symput('invar1','unempl') ;

1107 call symput('product1','1st_mtg') ;

1108 call symput('unempl_perc1','_down20') ;

1109 call symput('gvar1','exp_m_EL') ;

1110 run ;

NOTE: DATA statement used (Total process time):

real time 0.00 seconds

cpu time 0.01 seconds

 

1111 %macro fuss ;

1112 %do i = 1 %to 1 ; %put "stick1 &&invar&i.." ;

1113 *loop through the products ;

1114 %do j = 1 %to 1 ; %put "stick2 &&product&j.." ;

1115 *loop through the graph variables ;

1116 %do k = 1 %to 1 ; %put "stick3 &&gvar&k.." ;

1117 %put "&&invar&i.._perc1 &invar1. &unempl_perc1." ;

1118 %put "&&&gvar&k.._&&&&invar&i.._perc1. ";

1119 %end ;%end ;%end ;run ;%mend fuss ;run;

1120 %fuss ;

SYMBOLGEN: && resolves to &.

SYMBOLGEN: Macro variable I resolves to 1

SYMBOLGEN: Macro variable INVAR1 resolves to unempl

"stick1 unempl"

MPRINT(FUSS): *loop through the products ;

SYMBOLGEN: && resolves to &.

SYMBOLGEN: Macro variable J resolves to 1

SYMBOLGEN: Macro variable PRODUCT1 resolves to 1st_mtg

"stick2 1st_mtg"

MPRINT(FUSS): *loop through the graph variables ;

SYMBOLGEN: && resolves to &.

SYMBOLGEN: Macro variable K resolves to 1

SYMBOLGEN: Macro variable GVAR1 resolves to exp_m_EL

"stick3 exp_m_EL"

SYMBOLGEN: && resolves to &.

SYMBOLGEN: Macro variable I resolves to 1

SYMBOLGEN: Macro variable INVAR1 resolves to unempl

SYMBOLGEN: Macro variable INVAR1 resolves to unempl

SYMBOLGEN: Macro variable UNEMPL_PERC1 resolves to _down20

"unempl_perc1 unempl _down20"

SYMBOLGEN: && resolves to &.

SYMBOLGEN: Unable to resolve the macro variable reference &gvar

SYMBOLGEN: && resolves to &.

SYMBOLGEN: Macro variable K resolves to 1

SYMBOLGEN: && resolves to &.

SYMBOLGEN: && resolves to &.

SYMBOLGEN: Macro variable I resolves to 1

SYMBOLGEN: Macro variable GVAR1 resolves to exp_m_EL

SYMBOLGEN: && resolves to &.

SYMBOLGEN: Macro variable INVAR1 resolves to unempl

"exp_m_EL_unempl_perc1. "

MPRINT(FUSS): run ;

1121 run;

 

1 ACCEPTED SOLUTION

Accepted Solutions
Tom
Super User Tom
Super User

Macro arrays (a name commonly used for a series of macro variables with numeric suffices) are generally more confusion than they are worth.  If you can find another way to do what you want without using them I recommend it.

 

The rules for multiple & are simple. If there are two together then they are replaced by one and the macro process will scan the result for more macro resolutions.  Let's simplify your example.  You have one array member (INVAR1) that you want to use as part of the name of another array member (UNEMPL_perc1). 

%let invar1=unempl;
%let unempl_perc1= _down20;

First let's see how to generate references to these two variables using a dynamic numeric suffix.

%let i=1;
%put '&&invar&i' &&invar&i ;
%put '&&unempl_perc&i' &&unempl_perc&i ;

Second we can combine them together (and remember to add in periods to let macro processor know where macro references end). 

%put '&&invar&i.._perc&i' &&invar&i.._perc&i;

But that just returns the NAME of the macro variable.  To get it to resolve that name into a value we need to add more &.

%put '&&&&&&invar&i.._perc&i' &&&&&&invar&i.._perc&i;

To see why break it down into the individual passes that the macro process makes on the string.

%put 'Pass 1 = &&&invar1._perc1' &&&invar1._perc1;
%put 'Pass 2 = &unempl_perc1' &unempl_perc1;
%put 'Pass 3 = _down20';

The first pass will replace the '&i.' with their values and all of the double '&&' with single '&'.

The second pass will replace '&invar1' with its value and replace the double '&&' with a single '&'.

Now on the third and final pass the value of '&unempl_perc1' is replaced with its value.

 

Note that it is probably easier and clearer to others if you build the name first and then expand the value of the name.

%let mvar=&&invar&i.._perc&i;
%put &&&mvar;

 

View solution in original post

4 REPLIES 4
Tom
Super User Tom
Super User

Macro arrays (a name commonly used for a series of macro variables with numeric suffices) are generally more confusion than they are worth.  If you can find another way to do what you want without using them I recommend it.

 

The rules for multiple & are simple. If there are two together then they are replaced by one and the macro process will scan the result for more macro resolutions.  Let's simplify your example.  You have one array member (INVAR1) that you want to use as part of the name of another array member (UNEMPL_perc1). 

%let invar1=unempl;
%let unempl_perc1= _down20;

First let's see how to generate references to these two variables using a dynamic numeric suffix.

%let i=1;
%put '&&invar&i' &&invar&i ;
%put '&&unempl_perc&i' &&unempl_perc&i ;

Second we can combine them together (and remember to add in periods to let macro processor know where macro references end). 

%put '&&invar&i.._perc&i' &&invar&i.._perc&i;

But that just returns the NAME of the macro variable.  To get it to resolve that name into a value we need to add more &.

%put '&&&&&&invar&i.._perc&i' &&&&&&invar&i.._perc&i;

To see why break it down into the individual passes that the macro process makes on the string.

%put 'Pass 1 = &&&invar1._perc1' &&&invar1._perc1;
%put 'Pass 2 = &unempl_perc1' &unempl_perc1;
%put 'Pass 3 = _down20';

The first pass will replace the '&i.' with their values and all of the double '&&' with single '&'.

The second pass will replace '&invar1' with its value and replace the double '&&' with a single '&'.

Now on the third and final pass the value of '&unempl_perc1' is replaced with its value.

 

Note that it is probably easier and clearer to others if you build the name first and then expand the value of the name.

%let mvar=&&invar&i.._perc&i;
%put &&&mvar;

 

grezek
Obsidian | Level 7

Tom,

 

Thank you very much for your solution and detailed explanation.  This helps me out quite a bit!  -- George

Ksharp
Super User

options mlogicnest mprintnest mlogic mprint symbolgen;
grezek
Obsidian | Level 7

Mlogicnest and mprintnest --I'd never seen these.  Thank you very much!

SAS Innovate 2025: Save the Date

 SAS Innovate 2025 is scheduled for May 6-9 in Orlando, FL. Sign up to be first to learn about the agenda and registration!

Save the date!

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
  • 4 replies
  • 1365 views
  • 0 likes
  • 3 in conversation