Hello,
I would like to know whether it is possible to call marco variables with a looping code. Please see example below:
when i=1, I would like to get: _inval{1}=put( _invars{1},&_width1).
Current codes won't work.
data df1; a = .; b=1; c=1; output; a = 1; b=.; c=1; output; a = 1; b=1; c=.; output; run; %let _width1=3.1; %let _width2=3.2; %let _width3=3.3; data want ; set df1; array _invars{3} a b c; array _inval{3} $16 ; do i=1 to 3.; _inval{i}=put( _invars{i},&_widthi) ; /*I want to use &_width(i) where i change with i in looping setting */ end; run ;
I'd say, with OP setup there is no need for macro variables.
The PUTN which @PeterClemmensen mentioned is all is needed:
data df1;
a = .; b=1.235; c=1.234; output;
a = 1.234; b=.; c=1.234; output;
a = 1.234; b=1.234; c=.; output;
run;
data want ;
set df1;
array _invars{3} a b c;
array _inval{3} $16 ;
do i = 1 to 3;
_inval{i}=putn(_invars{i}, cats("5.",i)); /* build "5.i" text */
end;
put _all_;
run;
Bart
This is a classic SAS macro issue of timing. There are two main things you need to change in your code.
I changed the input values a bit, to make the result clearer. Feel free to ask.
data df1;
a = .; b=1.235; c=1.234; output;
a = 1.234; b=.; c=1.234; output;
a = 1.234; b=1.234; c=.; output;
run;
%let _width1=5.1;
%let _width2=5.2;
%let _width3=5.3;
data want ;
set df1;
array _invars{3} a b c;
array _inval{3} $16 ;
do i = 1 to 3;
f = symget(cats('_width', i));
_inval{i}=putn(_invars{i}, f);
end;
run;
Result:
a b c _inval1 _inval2 _inval3 i f . 1.235 1.234 . 1.24 1.234 4 5.3 1.234 . 1.234 1.2 . 1.234 4 5.3 1.234 1.234 . 1.2 1.23 . 4 5.3
I'd say, with OP setup there is no need for macro variables.
The PUTN which @PeterClemmensen mentioned is all is needed:
data df1;
a = .; b=1.235; c=1.234; output;
a = 1.234; b=.; c=1.234; output;
a = 1.234; b=1.234; c=.; output;
run;
data want ;
set df1;
array _invars{3} a b c;
array _inval{3} $16 ;
do i = 1 to 3;
_inval{i}=putn(_invars{i}, cats("5.",i)); /* build "5.i" text */
end;
put _all_;
run;
Bart
@PeterClemmensen Thanks so much!👍Can we do
putn(_invars{i}, &_width1.)
directly? I got error message for "expecting a format" 😅
One question might be very silly. How can I tell when an 'i' will change base on the looping i setup? I was hoping the i in &widthi will change when I do looping. Could you guide me on this? Thanks.
You have an error because PUTN() function (go to see its documentation: https://documentation.sas.com/doc/en/pgmsascdc/9.4_3.5/lefunctionsref/p12zqzvwx4dv6kn1p9crijxswolk.h... , unfortunatell the description there in vague)
expects a string constant or a character variable/expression which provides format name.
For example if
%let _width1=best32.20;
then your code should be:
/* option 1 */
putn(_invars{i}, "&_width1.")
/* option 2 */
putn(_invars{i}, symget("_width1"))
Basically, think about it that you want to have:
putn(variable, "format-name.")
/* or */
xxx="format-name.";
putn(variable, xxx)
Bart
@stataq wrote:
@PeterClemmensen Thanks so much!👍Can we do
putn(_invars{i}, &_width1.)
directly? I got error message for "expecting a format" 😅
One question might be very silly. How can I tell when an 'i' will change base on the looping i setup? I was hoping the i in &widthi will change when I do looping. Could you guide me on this? Thanks.
Remember that the macro processor is a PRE processor. The results after the macro processor has finished needs to be valid SAS code.
So what value did _WIDTH1 have? If it was just 5.3 (without any quotes) then your statement becomes something like:
putn(x,5.3)
Which is not valid SAS code because the PUTN() function wants a character value for the second argument (and a numeric value for the first. If you are formatting a character string use the PUTC() function instead.). In this context the string 5.3 is a number, not a character string. It might be interpreted as a format specification in locations where such was expected, but that is not what PUTN() expects.
So either add the quotes when referencing the macro variable:
putn(x,"&_width1")
Or make sure the quotes are in the macro variable.
%let _width1="5.3";
So that the resolved SAS code is something like:
putn(x,"5.3")
No need for macro variables. Just put the formats into another array.
data want ;
set df1;
array _invars a b c;
array _inval[3] $16 ;
array _formats[3] $8 _temporary_ ('5.1' '5.2' '5.3');
do i=1 to 3.;
/*I want to use &_width(i) where i change with i in looping setting */
_inval[i]=putN( _invars[i],_formats[i]);
end;
run ;
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.
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.
Ready to level-up your skills? Choose your own adventure.