BookmarkSubscribeRSS Feed
mansour_ibrahim
Obsidian | Level 7
Hello,

I can not understand why cat does not take into account the zeros in this example.
The length of the macro variable x3 is 2 for months <10 after put (x2,Z2.). Another question, why the repeat function when the number of repetitions equal to 0
adds the 0 (which explains the use of the loop)
%macro remplir();
%DO LOOP=7 %to 12;
%LET x1=%SYSFUNC(INTNX(month,%SYSFUNC(INTNX(day,%SYSFUNC(today()),%SYSFUNC(day(%SYSFUNC(today())))-1)),&LOOP.-19));
%LET x2=%SYSFUNC(MONTH(&x1.));
%LET x3=%SYSFUNC(PUTN(&x2., Z2.));
%let len=%length(&x3.);
%let len1=%length(&x2.);
%LET val1=&x1.;
%LET val12=%SYSFUNC(CAT(%SYSFUNC(PUTN(&x1.,year2.)),M,&x3.));
%LET val13=%SYSFUNC(CAT(%SYSFUNC(PUTN(&x1.,year2.)),M,%sysfunc(repeat(0,%eval(2-%length(&x2.)))) ,&x2.));
%if &len1.=1 %then %do;
%LET val14=%SYSFUNC(CAT(%SYSFUNC(PUTN(&x1.,year2.)),M,%sysfunc(repeat(0,%eval(2-%length(&x2.)))) ,&x2.));
%end;
%else %do;
%LET val14=%SYSFUNC(CAT(%SYSFUNC(PUTN(&x1.,year2.)),M,&x3.));
%end;
%put &=x3/&=len./&=val12./&=val12./&=val13./&=val14.;
%end;
%mend remplir;
%remplir; 
/**************/
Log
/*************/


 Log
X3=11/LEN=2/VAL12=16M11/VAL12=16M11/VAL13=16M011/VAL14=16M11
X3=12/LEN=2/VAL12=16M12/VAL12=16M12/VAL13=16M012/VAL14=16M12
X3=01/LEN=2/VAL12=17M1/VAL12=17M1/VAL13=17M01/VAL14=17M01
X3=02/LEN=2/VAL12=17M2/VAL12=17M2/VAL13=17M02/VAL14=17M02
X3=03/LEN=2/VAL12=17M3/VAL12=17M3/VAL13=17M03/VAL14=17M03
X3=04/LEN=2/VAL12=17M4/VAL12=17M4/VAL13=17M04/VAL14=17M04
cordially

 

6 REPLIES 6
Kurt_Bremser
Super User

Why, in $DEITY's name, are you doing that in a macro? The macro facility is a CODE GENERATOR, not a DATA PROCESSOR!!!. Use a data step!

 

That %sysfunc avalanche is a cancer-causing eyesore.

 

In the data step, use put's whenever you assign/create a variable, to see how your data is modified. The data step also notifies you of all automatical type conversions where formats might be lost.

RW9
Diamond | Level 26 RW9
Diamond | Level 26

Sorry, that code is nigh on impossible to read.  Why not use a simple datastep to achieve your goal?

data _null_;
  do i=7 to 12;
    /* do some things here */
  end;
  call symput('len',lengthn(...));
...
run;

Though I can't actually see why you would need all those macro variables in the first place.  It would be far simpler if you put the calculation output in datasets and used merges - or are you planning on using this information in filenames/dataset names?  If so consider doing all the programming using one dataset and split it out at the end - will simplfy coding quite a bit.

mansour_ibrahim
Obsidian | Level 7

Thank you for your answers

I simplify the example.

Why cat does not take into account the 0?

%let x1=2010;
%LET x2=01;
%LET x3=%SYSFUNC(CAT(&x1.,M,&x2.));
%put &x3.;
RW9
Diamond | Level 26 RW9
Diamond | Level 26

Oh, and to fix it just do:

%let x1=2010;
%let x2=01;
%let x3=&x1.M&x2.;
%put &x3.;

You don't need cat() at all.

 

 

 

You will find this post helpful:

https://communities.sas.com/t5/General-SAS-Programming/Why-is-CAT-removing-leading-zeros/td-p/329883

 

As always, the problem lies with doing data processing in macro language.  Macro is for generating text, nothing more, and has limited functionality.  In your case the cat() function is treating 01 as numeric, which is 1.  You can use put in there as well, however best method is to use the tool appropriate to the task, and data processing is best done in Base SAS - in fact macro is just an addon.

Kurt_Bremser
Super User

cat DOES take leading zeroes into account:

data _null_;
x1 = '2017';
x2 = '09';
x3 = cat(x1,'M',x2);
put x3=;
run;

Result:

2017M09

But try this:

data _null_;
x1 = 2017;
x2 = 09;
x3 = cat(x1,'M',x2);
put x3=;
run;

Result:

x3=2017M9

So you can see that your "problem" comes from your abuse of the macro facility.

ballardw
Super User

Looks like an awful lot of work to simulate the use of the YYMMw. format with.

 

Generally you are better off leaving dates as date values until a human has to read them.

 

For instance

data _null_;
   x= '15Dec2016'd;
   put x yymm5.;
run;

which is the value of your macro variables Val12 and Val14 on the second line of log output. (picked on December of personal reasons)

 

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!

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
  • 6 replies
  • 1254 views
  • 2 likes
  • 4 in conversation