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

Hello, there:

 

 

I would like to generate macro variable that includes same strings repeatedly, and that has name I want.

I have 3 ideas (for more details, please see below), and like Pattern 3, I would like to generate macro variable with name I want in same step (in MACRO setting).

 

But after submitting Pattern 3 code, I get WARNING. I do not know why and how to resolve this problem.

If you have any ideas, please let me know. Any ideas would be welcome.

Thank you in advance.

 

***** Pattern 1 ;

In this pattern, I have to define null macro variable first.

* Pattern 1: Define MACRO VARIABLEs in advance ;
***** First, you have to define MACRO VARIABLEs you want ;
%let re5=;

***** Second, specify word you want to repeat ;
%let t=WORD;

***** MACRO Setting ;
%macro re(max=);
data re(drop=i);
    length re $2000.;
    array ar1(*) $ re1-re&max.;
    do i=1 to dim(ar1);
        ar1(i)='&t';
    end;
    re=catx(" ", of re1-re&max.);
run;
proc sql noprint;
    select re into :re&max.
    from work.re
    ;
quit;
%mend re;

***** Finally, generate MACRO VARIABLE & check content ;
%re(max=5)
%put &re5.;
***** If you don't define MACRO VARIABLEs in advance, get WARNING ;
%re(max=100)
%put &re100.;

***** Pattern 2 ;

In this pattern, after submitting MACRO, I have to define macro variable with name I want.

* Pattern 2: After setting MACRO, Store MACRO VARIABLEs with name you want ;
***** First, specify word you want to repeat ;
%let t=WORD;

***** MACRO Setting ;
%macro re(max=);
data re(drop=i);
    length re $2000.;
    array ar1(*) $ re1-re&max.;
    do i=1 to dim(ar1);
        ar1(i)='&t';
    end;
    re=catx(" ", of re1-re&max.);
run;
%mend re;

***** Second, submit your MACRO ;
%re(max=10)

***** Finally, generate MACRO VARIABLE with name you want & check ;
proc sql noprint;
    select re into :re10
    from work.re
    ;
quit;
%put &re10.;

***** Pattern 3 ;

In this pattern, I think I can generate macro variable with name I want, but this code does not work.....

* Pattern 3: In same step (MACRO Setting), generate MACRO VARIABLE with name you want ;
***** NOTE: There're some problems in this method ;
***** First, specify word you want to repeat ;
%let t=WORD;

***** MACRO Setting ;
%macro re(max=);
data re(drop=i);
    length re $2000.;
    array ar1(*) $ re1-re&max.;
    do i=1 to dim(ar1);
        ar1(i)='&t';
    end;
    re=catx(" ", of re1-re&max.);
run;
********** At here, in MACRO Setting, I want to generate MACRO VARIABLE with name I want, but something is wrong..... ;
data _null_;
    set re;
    call symputx("re&max.", re);
run;
%mend re;

***** Finally, generate MACRO VARIABLE & check content ;
%re(max=15)
%put &re15.; * <----------Submit WARNING ?????????? ;

 

1 ACCEPTED SOLUTION

Accepted Solutions
Shmuel
Garnet | Level 18

In your code:

%let txt=%str(WORD );
%macro re(max=);
data _null_;
    length re $2000.;
    re=repeat("&txt", &max.-1);
    call symputx("re&max.", strip(re));
run;
%mend re;
%re(max=10)
%put &re10.;

the RE&max macro variable is created inside the macro code, which means it is by default local macro variable.

You need to add %global re&max; statement inside the macro.

View solution in original post

10 REPLIES 10
Shmuel
Garnet | Level 18

Try next code:

%let txt=any string # ;
%let n =3;

data _NULL_;
  length long_string = repeat("&txt", &n-1);
  call symput('Check', strip(long_string));
run;

%put &check;

KentaMURANAKA
Pyrite | Level 9

Hi, Shmuel-san:

 

 

Thank you for quick reply & your code is simple, wonderful.

I did not know REPEAT function.

Below works.

%let txt=%str(WORD );
%let max=5;
data _null_;
    length re $2000.;
    re=repeat("&txt", &max.-1);
    call symputx("re&max.", strip(re));
run;
%put &&re&max..;

But I want to use multiple macro variables like RE5 (5 times repeated), or RE10 (10 times repeated), etc., so if possible, I want to conduct this operation in MACRO. Referring to your code, I tried to create this MACRO, but I get WARNING.

%let txt=%str(WORD );
%macro re(max=);
data _null_;
    length re $2000.;
    re=repeat("&txt", &max.-1);
    call symputx("re&max.", strip(re));
run;
%mend re;
%re(max=10)
%put &re10.;

Do you know why and how to resolve this?

 

 

Thank you in advance.

Shmuel
Garnet | Level 18

In your code:

%let txt=%str(WORD );
%macro re(max=);
data _null_;
    length re $2000.;
    re=repeat("&txt", &max.-1);
    call symputx("re&max.", strip(re));
run;
%mend re;
%re(max=10)
%put &re10.;

the RE&max macro variable is created inside the macro code, which means it is by default local macro variable.

You need to add %global re&max; statement inside the macro.

KentaMURANAKA
Pyrite | Level 9

Hi, Shmuel-san:

 

 

Thank you, I understand!!

 

In summary, 

KurtBremser-san's idea is.....

%macro re(var=, txt=, rep=);
%global &var.;
%let &var.=;
%do i=1 %to &rep.;
%let &var.=&&&var. &txt.;
%end;
%mend re;

%re(var=re10, txt=WORD, rep=10)
%put &re10.;

and Shmuel-san's idea is.....

%let txt=%str(WORD );
%macro re(max=);
%global re&max.;
data _null_;
    length re $2000.;
    re=repeat("&txt", &max.-1);
    call symputx("re&max.", strip(re));
run;
%mend re;
%re(max=7)
%put &re7.;

I think both ideas are wonderful.

Thank you, Shmuel-san, KurtBremser-san!!

Kurt_Bremser
Super User

I usually prefer to build my macro variables in data steps, as the syntax is simpler, and I do not need %sysfunc to use data step functions.

But here there are two factors:

  • concatenating is extremely easy in macro language, as you can see
  • by only using macro code, this macro can be placed right in the middle of a data or procedure step, without causing a step boundary
KentaMURANAKA
Pyrite | Level 9

Hi, KurtBremser-san:

 

 

I think same as you.

I almost always create macro variables in DATA step (or SQL step),

so for me, your idea is eye-opener.

 

 

Thank you !

Kurt_Bremser
Super User

You can do it in the macro without using an additional data step, and it's not even complicated:

%macro repeat_text(varname,text,rep);
%global &varname.;
%let &varname.=;
%do i = 1 %to &rep.;
  %let &varname=&&&varname. &text.;
%end;
%mend;

%repeat_text(re,word,3)

%put &re.;

Log:

37         %macro repeat_text(varname,text,rep);
38         %global &varname.;
39         %let &varname.=;
40         %do i = 1 %to &rep.;
41           %let &varname=&&&varname. &text.;
42         %end;
43         %mend;
44         
45         %repeat_text(re,word,3)
46         
47         %put &re.;
word word word
KentaMURANAKA
Pyrite | Level 9

Hi, KurtBremser-san:

 

 

Thank you for reply. Your code worked! Aha!

%macro re(var=, txt=, rep=);
%global &var.;
%let &var.=;
%do i=1 %to &rep.;
%let &var.=&&&var. &txt.;
%end;
%mend re;

%re(var=re10, txt=WORD, rep=10)
%put &re10.;

 I think three ampersands are important (I do not understand why).

Anyway, thank you, KurtBremser-san, Shmuel-san!!

Kurt_Bremser
Super User

Regarding the three ampersands:

When the macro processor resolves macro triggers (& or %), it can and will do so repeatedly.

Two ampersands are converted to one on each pass, so what happens is this:

Pass 1:

&&&varname. -> & (converted from the first two ampersands) re10 (content of macro variable &varname)

so you get

&re10

(the dot is removed; if this was part of some longer string, you also need to add additional dots for each pass)

Pass 2:

&re10. --> (contents of &re10)

 

KentaMURANAKA
Pyrite | Level 9

Hi, KurtBremser-san:

 

 

Thank you for your kind advice. I understand now!

Regarding to "%let &var.=&&&var.. &txt.",

first "&var." means variable name,

and second "&&&var.." means, not variable name, it means variable content.

 

 

Thank you!!

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
  • 10 replies
  • 2602 views
  • 5 likes
  • 3 in conversation