Inside a data step you probably really shouldn't use the the macro function %sysfunc. You value gets treated by the macro processor not the data step.
Try
hhldid_date=cat(hhldid,put(&month,z3.),&year));
Inside a data step you probably really shouldn't use the the macro function %sysfunc. You value gets treated by the macro processor not the data step.
Try
hhldid_date=cat(hhldid,put(&month,z3.),&year));
CAT function accepts both numeric and character arguments. As written, after the macro processing is done you have given the CAT function something that looks like a number, so it treats it as a number and ignores leading zeros. If you want it to treat it as character you need to add quotes, i.e.:
HHLDID_date= cat(HHLDID,"%sysfunc(putn(&MONTH,z3.))&year");
The quotes don't have meaning in the macro language, but int he data step language they tell the CAT function that the argument is a character literal value.
Here is a little example:
%let month=02;
%let year=2017;
data want;
HHLDID="Some Text";
try1= cat(HHLDID,%sysfunc(putn(&MONTH,z3.))&year);
put try1=;
try2= cat(HHLDID,"%sysfunc(putn(&MONTH,z3.))&year");
put try2=;
run;
CAT see's it as numeric and according to the docs:
If item is numeric, then its value is converted to a character string by using the BESTw. format.
You typically don't need the CAT function in macro though.
You're in a data step so you don't need the %SYSFUNC either.
HHLDID_date= cat(HHLDID, put(&MONTH,z3.), &year);
Just for the sake of discussion, I actually like the %SYSFUNC() approach better here.
Compare:
HHLDID_date= cat(HHLDID,"%sysfunc(putn(&MONTH,z3.))&year") ;
HHLDID_date= cat(HHLDID, put(&MONTH,z3.), &year) ;
&Month is is a constant stored in a macro variable, as is &Year.
If you use the first approach, the %sysfunc() is executed only once when the macro executes. With the second approach, the PUT() function will execute once for every observation, as the DATA step executes.
With moderately sized data, I would expect a small efficiency gain from the first approach, but this sort of efficiency doesn't matter much to me.
I mostly like the first approach for clarity (though many may disagree : ) I think it's clearer to use the data step language to manipulate data step variables, and use the macro language to manipulate macro variables.
If I thought I needed the macro side I would probably actually use
%let newmonth= %sysfunc(putn(&month,z3.))&year;
and then use &newmonth so there was only a single macro variable referenced inside the data step in that CAT.
I believe the original issue actually was that the result of the %sysfunc, whic was 001 behave like
var= cat(othervar,0012016); which uses the best format to convert the 0012016 to the string before concatenating. So I think you might need "%sysfunc(putn(&month,z3))&year" inside the cat function.
Thanks for all the tips. Worked and I got my datasets prepared!
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!
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.