BookmarkSubscribeRSS Feed
FreelanceReinh
Jade | Level 19

Hello @mansour_ib_sas,

 

When CATX is called for the first time (by %SYSFUNC), macro variable F contains only a blank, which is regarded equal to a null (i.e. empty) value in macro variable comparisons because trailing blanks are ignored. It appears to me that this lack of "character contents" triggers the %SYSEVALF function to evaluate &F numerically. After all, the CATX function does not only concatenate character strings, but also numeric arguments (which are converted to a character string, but only after evaluation), so &F could very well be a numeric expression which might contain non-integer operands and hence would need evaluation by %SYSEVALF. Calling %SYSEVALF with an empty argument, however, results in the error message you've reported (try %let x=%sysevalf();).

 

To avoid the error message you could apply %IF/%THEN logic to start with CATX calls only after F has been populated with the first "word" of the character string in macro variable A. However, I would recommend to perform the concatenation in the form

%let f=&f "%scan(&a,&i,%str( ))";

because this is simpler and doesn't require CATX at all (hence the error message cannot occur).

 

Note that I replaced your single blank in single quotes (' ') by %str( ) because those single quotes in a %SYSFUNC call would be interpreted as ordinary characters, here: delimiters, which is probably not what you intended. (So, please do the same in your COUNTW call.) Also, the initialization of macro variable F can be simplified to %let f=;.

Tom
Super User Tom
Super User

There is no need to use the CAT... functions to concatenate macro variables.  Just expand the values where you want them and they will automatically be concatenated.  If you want something like a space between the values the just do:

 

%let f=&f "%scan(&a,&i,%str( ))";

So if F is already empty the leading space before the quote will be ignored by the %LET.

 

If you need to something other than space as the delimiter you might need to take special care to not add one in the front.

You could start your loop at 2.

%let f="%scan(&a,1,%str( ))";
%do i=2 %to ....

You could test and treat the first value differently.

 

What I like to do for this "catx" type structure is use a different macro variable to contain the separation character (string) and set it empty to start and then set it after the first "concatenation".  Then no need for %IF logic.

For example to make a comma separated list.

%let f=;
%let sep=;
%do i=1 %to %sysfunc(countw(&a,%str( )));
  %let f=&f.&sep."%scan(&a,&i,%str( ))";
  %let sep=,;
%end;

 

 

 

mansour_ib_sas
Pyrite | Level 9

Now it's good. Thank you for your pertinents comments

%macro tt();
%global f;
%let a=001-001 001-002;
%let f=;
%do i=1 %to %sysfunc(countw(&a.,%str( )));
%let f=&f. "%scan(&a.,&i,%str( ))" ;
%end;
%mend;
%tt;

%put f=&f.;

SAS Innovate 2025: Call for Content

Are you ready for the spotlight? We're accepting content ideas for SAS Innovate 2025 to be held May 6-9 in Orlando, FL. The call is open until September 25. Read more here about why you should contribute and what is in it for you!

Submit your idea!

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
  • 17 replies
  • 24644 views
  • 9 likes
  • 10 in conversation