DATA Step, Macro, Functions and more

Used function cat for numeric number with format zw.

Reply
Occasional Contributor
Posts: 19

Used function cat for numeric number with format zw.

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

 

Super User
Posts: 7,846

Re: Used function cat for numeric number with format zw.

Posted in reply to mansour_ibrahim

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.

---------------------------------------------------------------------------------------------
Maxims of Maximally Efficient SAS Programmers
Super User
Super User
Posts: 7,981

Re: Used function cat for numeric number with format zw.

Posted in reply to mansour_ibrahim

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.

Occasional Contributor
Posts: 19

Re: Used function cat for numeric number with format zw.

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.;
Super User
Super User
Posts: 7,981

Re: Used function cat for numeric number with format zw.

[ Edited ]
Posted in reply to mansour_ibrahim

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.

Super User
Posts: 7,846

Re: Used function cat for numeric number with format zw.

Posted in reply to mansour_ibrahim

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.

---------------------------------------------------------------------------------------------
Maxims of Maximally Efficient SAS Programmers
Super User
Posts: 11,343

Re: Used function cat for numeric number with format zw.

Posted in reply to mansour_ibrahim

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)

 

Ask a Question
Discussion stats
  • 6 replies
  • 103 views
  • 2 likes
  • 4 in conversation