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

Hello Community,

 

I am writing some program in SAS, where I would like to define a arbitrarily long list of parameters by a %LET statement:

%let Countries = US, DE, IT;

I would like to keep the definition of parameters as simple and convenient as possible, as later on different users will use this code ...

 

To handle the parameters later in the code, I basically need to things:

  1. A string like US_DE_IT for naming data sets.
  2. A string like 'US', 'DE', 'IT' to place it in a WHERE statement.

If possible, I would like to NOT do it via a macro but work with %LET and %SYSFUNC.

 

For point 1, I was able to do so via:

%let strCountries = %sysfunc(compress(%sysfunc(tranwrd(%quote(&Countries),%quote(,),_))));

et voilà:

%put &strCountries;
US_DE_IT

For point 2, my idea was to take &strCountries (US_DE_IT) and replace _ with ', ' and add a leading and trailing '. I think this should result in: 'US', 'DE', 'IT'...

 

Code for "in beween" ',' looks as follows:

%let listCountries = %sysfunc(tranwrd(&strCountries,_,', '));

If a run this a get an error, stating:

 

NOTE 49-169: The meaning of an identifier after a quoted string may change in a future SAS release.  Inserting white space between a quoted string and the succeeding identifier is recommended.

 

 

What do I need to do? Any suggestions how I could point 1 and 2 done?

 

Thank you!

1 ACCEPTED SOLUTION

Accepted Solutions
Kurt_Bremser
Super User

A NOTE is a note and not an error. This particular NOTE appears when a character follows immediately after a trailing single or double quote of a string literal. This is because such a character might carry special meaning, like in

"01jan2016"d

and new special meanings might be added by SAS in the future.

 

I suggest to do your string manipulation in a data _null_ step:

%let Countries = US, DE, IT;
data _null_;
length outstring1 outstring2 $20;
do i = 1 to countw("&countries",',');
  outstring1 = catx('_',trim(outstring1),strip(scan("&countries",i,',')));
  outstring2 = catx(',',trim(outstring2),"'"!!strip(scan("&countries",i,','))!!"'");
end;
call symput('strcountries',trim(outstring1));
call symput('listcountries',trim(outstring2));
run;
%put &strcountries;
%put &listcountries;

View solution in original post

7 REPLIES 7
Kurt_Bremser
Super User

A NOTE is a note and not an error. This particular NOTE appears when a character follows immediately after a trailing single or double quote of a string literal. This is because such a character might carry special meaning, like in

"01jan2016"d

and new special meanings might be added by SAS in the future.

 

I suggest to do your string manipulation in a data _null_ step:

%let Countries = US, DE, IT;
data _null_;
length outstring1 outstring2 $20;
do i = 1 to countw("&countries",',');
  outstring1 = catx('_',trim(outstring1),strip(scan("&countries",i,',')));
  outstring2 = catx(',',trim(outstring2),"'"!!strip(scan("&countries",i,','))!!"'");
end;
call symput('strcountries',trim(outstring1));
call symput('listcountries',trim(outstring2));
run;
%put &strcountries;
%put &listcountries;
AndreasF
Fluorite | Level 6

Thank you very much. Works perfect. Some new commands for me, so it really helps me. 🙂

 

BTW: How have you been able to make your code look like in SAS?

 

Regards!

Kurt_Bremser
Super User

Use the "little running man" icon to open an editor window where the editor formats the code quite like the enhanced editor in SAS (after posting).

 

I usually use the data step technique to compose macro variables to avoid complicated sequences of %sysfunc's and quoting/unquoting functions.

TBH, I have no clue when to use the quoting functions. Never need them in a data step.

RW9
Diamond | Level 26 RW9
Diamond | Level 26

Sounds like a total faff to me.  Putting lists in macro variables is never the best way to do things but will make you write spaghetti code to handle it.  What exactly is it your trying to do?  If you need to loop of a set of data (clues in the title here) then put your data in a dataset, then use that to roll off the other code, either macro or generated.  Eg.

data _null_;
  set listofcountrycodes;
  call execute(cats('%macro DoSomething (country=',country,');');
run;
AndreasF
Fluorite | Level 6

Thanks for your input. I am very happy with the solution KurtBremser provided.

 

For my program, users should be able to easily and fast change the list of countries. The %LET statement is the most convenient way I could think of.

 

 

ballardw
Super User

Please be aware that when you use a macro variable with commas such as your %let Country = US, IT, DE; that if you attempt to use that as a parameter for a macro you are almost always going to get either unexpected results or an error of "more positional parameters than declared" type error.

Tom
Super User Tom
Super User

If your values are simple country codes like in your example (that is no embedded commas or spaces in the individual item values) I would recommend telling the users to NOT enter any commas.  But that might be difficult to enforce so you might see values like this in the user generated %LET statements.

%let Countries = US,   DE,   IT;
%let Countries = US DE IT;
%let Countries = us, De  IT;

You can convert that to a simple space delimited list using code like:

%let cleanCountries=%sysfunc(compbl(%sysfunc(translate(%qupcase(&countries),' ',','))));

This will fix the case, remove the commas and compress multiple spaces to just one. Note there is no need to macro quote the space or comma if they are inside of quotes. Translate will just convert any quotes it sees back to quotes since it matches the lists of characters convert element by element.

 

You can then convert that to your underscore delimited version:

%let listCountries=%sysfunc(translate(&cleanCountries,'_',' '));

You can also use your tranwrd method to convert to a list of quoted values.

%let strCountries=%unquote(%bquote('%qsysfunc(tranwrd(&listCountries,_,' '))'));

You could use commas instead of spaces between the quoted strings if you want, but note that SAS is happy to use the space delimited list instead of comma delimited list.  For example when using the IN operator.

where countryCode in ('US' 'DE' 'IT');

 

sas-innovate-2024.png

Join us for SAS Innovate April 16-19 at the Aria in Las Vegas. Bring the team and save big with our group pricing for a limited time only.

Pre-conference courses and tutorials are filling up fast and are always a sellout. Register today to reserve your seat.

 

Register now!

SAS Enterprise Guide vs. SAS Studio

What’s the difference between SAS Enterprise Guide and SAS Studio? How are they similar? Just ask SAS’ Danny Modlin.

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
  • 7 replies
  • 4233 views
  • 1 like
  • 5 in conversation