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

I know how to assign a straight list of macro variables to one macro variable each, but how do you do it so each value in the list is it's own macro variable as such:

each variable in the list will be of varying lengths and the list will be any number of variables up to N.

%let macrolist= var1 var2 var3 var4......varN;

Ultimately I want to get to this point, where cvar1, cvar2, cvar3....cvarN are the variables from the list above.

%do i=1 %to N;

call symput ('cvar'||(&i), var&i);

1 ACCEPTED SOLUTION

Accepted Solutions
Tom
Super User Tom
Super User

You seem to be saying that you want to split the list of words in &MACROLIST into separate variables.  Do you want just the text string? or the value of the macro variable that has that name?

Lets do both and call the resulting macro variables CVAR... and CVAL.... (for variable and value).

If we assume that you know the value of N then you can do:

%do i=1 to &n ;

   %let cvar&i = %scan(&macrolist,&i,%str( ));

   %let cval&i = &&&cvar&i ;

%end;

If you do not know the value of N then you will need to increment the counter variable (I in the code above) manually using %let i=%eval(&i + 1) and test for and empty result from the %scan() function call to terminate the loop.

If you want to be able to reference the new macro variables after the currently running macro finishes you might want to add a %global statement inside the %do loop.

NOTE: CALL SYMPUT is for use in regular SAS. You should be able to manipulate you macro variables with just macro logic and statements.

View solution in original post

12 REPLIES 12
art297
Opal | Level 21

Not sure if I correctly understand what you are asking.  You can create a macro variable using proc sql.  Thus you could use something like (untested):

proc sql noprint;

  select name into : wantlist

     separated by " "

       from dictionary.columns

          where libname="THELIBYOUWANT" and

           memname="THEFILEYOUWANT";

quit;

You can also incorporate a keep statement to limit which variables you want to include.

HTH,

Art

SASguyCO
Calcite | Level 5

Thanks for the reply Art.  If I understand you correctly, you are suggesting putting all the macro variables into 1 new macro variable, I'm talking about taking the list and separating each variable from 1.....to N and creating a new macro variable for each individual one, so that if there are 10 vars in the list, then there will be 10 macro variables.  I hope that makes sense.

Tom
Super User Tom
Super User

You seem to be saying that you want to split the list of words in &MACROLIST into separate variables.  Do you want just the text string? or the value of the macro variable that has that name?

Lets do both and call the resulting macro variables CVAR... and CVAL.... (for variable and value).

If we assume that you know the value of N then you can do:

%do i=1 to &n ;

   %let cvar&i = %scan(&macrolist,&i,%str( ));

   %let cval&i = &&&cvar&i ;

%end;

If you do not know the value of N then you will need to increment the counter variable (I in the code above) manually using %let i=%eval(&i + 1) and test for and empty result from the %scan() function call to terminate the loop.

If you want to be able to reference the new macro variables after the currently running macro finishes you might want to add a %global statement inside the %do loop.

NOTE: CALL SYMPUT is for use in regular SAS. You should be able to manipulate you macro variables with just macro logic and statements.

SASguyCO
Calcite | Level 5

Thanks Tom,

Yes, I'm trying to just capture the text string with each word broken apart from the original list. 

I've tried the following code and can't get this to work quite right...  Am I doing something wrong?  The value of &cvar1 should be "house".

%let macrolist = house garage car speaker;

%let n=4;

%macro assign;

     %do i=1 %to &n;

     %global;

          %let cvar&i=%scan(&macrolist,1,%str());

      %end;

%mend assign;

%assign;

%put cvar1;

Peter_C
Rhodochrosite | Level 12

replace the 1 with &i in the %scan

insert a blank within the brackets of %str()

define which var to global, fully like:

%global cvar&i ;

learn to develop macros with

option symbolgen ;

SASguyCO
Calcite | Level 5

Thank you Peter, that did the trick.  The 1 was an error on my part of typing as I did have the &i in the original.  I'm familiar with the symbolgen mprint mlogic as well, thank you. 

My question is I was able to run this not using the %str(' ') inside with the blank quotes and just using the empty single quotes alone ' '.  What is the purpose of the %str in this case?  I'm not familiar with the %str and thus was curious what it does here. 

thank you all for your help.

Tom
Super User Tom
Super User

The %str( ) is useful to prevent the macro processor from ignoring the space. When you use single quotes or double quotes around characters they actually become part of the string.

This means that %scan(&myvar,&i,%str( )) means something different than %scan(&myvar,&i,' ').

The first only uses blanks as the delimiter when scanning.  The second one will use either blanks or single quote characters.

SASguyCO
Calcite | Level 5

Thanks for the response Tom, makes sense. 

SASguyCO
Calcite | Level 5

Tom,

Regarding how to do this when N is unknown, I'm not sure how to do it with your recommendations above.  I've tried it several ways using a %do %while and %do %until and trying to determine if the value is blank to terminate the loop, but I keep getting errors.  Can you show me how I would do this if the N is unknown?

thanks again!

Tom
Super User Tom
Super User

As long as you are using SAS verison 9 you should be able to use the COUNTW function.

%let n=%sysfunc(countw(&macrolist));

Otherwise you can loop and increment your own counter.  You can either test for empty using something like:

%if (&var = ) %then ....

Or test for zero length

%if %length(&var)=0 %then ...

They test slightly different things, but for this problem they are equivalent as you are using blanks for your delimiter.

Here is one way to count. Remember to subtract one because it stops on an empty word.

%let n=1 ;

%do %while(%scan(&macrolist),&n) ne ) ;

    %let n=%eval(&n + 1);

%end;

%let n=%eval(&n -1 );

SASguyCO
Calcite | Level 5

Thanks again Tom!  Excellent solutions for sure!  The first one worked perfect just using the countw function which I was unaware of.

I tried the count one as well and that did the trick too.

Really appreciate it!

sas-innovate-2024.png

Available on demand!

Missed SAS Innovate Las Vegas? Watch all the action for free! View the keynotes, general sessions and 22 breakouts on demand.

 

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.

Click image to register for webinarClick image to register for webinar

Classroom Training Available!

Select SAS Training centers are offering in-person courses. View upcoming courses for:

View all other training opportunities.

Discussion stats
  • 12 replies
  • 1928 views
  • 6 likes
  • 4 in conversation