DATA Step, Macro, Functions and more

Macro modify macro variable value

Reply
Contributor
Posts: 41

Macro modify macro variable value

Hi,

 

I have a problem. I import a macro variable named P from a table. P is a date, ex in my case :01JAN2017

 

I also import another macro variable named D. D is a number, or can be empty or missing.

 

I want to do this in my macro:

%if "&D." ne . %then %do;
		%if "&D." ne '' %then %do;
			%let &P. = intnx('month',today(),&D.-1,"BEGINNING");
		%end;
%end;

And I have a mistake:

ERROR: Expecting a variable name after %LET.
ERROR: Symbolic variable name 01JAN2017 must begin with a letter or underscore.

Can you help me to correect this, i can't understand 

Thanks in advance. Smiley Happy

Moderator
Posts: 238

Re: Macro modify macro variable value

Just looking at the code (not able to run it at the moment), on the surface it looks like you just need to change:

  • %let &P = ...

to

  • %let P= ...
Super User
Super User
Posts: 7,401

Re: Macro modify macro variable value

Why do you have two if statements doing the same thing?  Why are you putting data in macro variables?  Why are you doing data processing in macro language? To answer your specific question requires a little debugging, which if your using macro you should know very well.  Macro is a text find/replace system, nothing more.  So if you do that on:

%let &P. = intnx('month',today(),&D.-1,"BEGINNING");

What you get in Base SAS - which is the actual programming language is:

%let 01JAN2017 = intnx('month',today(),01JAN2017-1,"BEGINNING");

Which you can clearly see is invalid SAS code, variables - and macro - have to start with a non-numeric character.

 

In any event the code given doesn't make much sense.  Why would you want a macro variable, and all that macro logic to increment a date by one day?  Simply doing:

%let p=01JAN2017;

data want;
  set have;
  where date > "&P."d + 1;
run;

Far simpler.  The text p gets replaced in the code to create acurate Base SAS code. 

Super User
Posts: 6,936

Re: Macro modify macro variable value

&P. resolves to the value of macro variable P, so your %let statement becomes

%let 01JAN2017 = intnx('month',today(),&D.-1,"BEGINNING");

Since SAS names cannot start with a digit, this fails. I guess you wanted to do

%let P = ....

I also question your logic here, as you assign a complete function call to your presumed macro variable P. P will not resolve to a date, but to the text

intnx('month',today(),2-1,"BEGINNING");

(supposing macro variable D contains 2), which might or might not work once you use &P. anywhere in SAS code.

If you want to calculate a date, I suggest you do so in a data step and save the resulting value to a macro variable with call symput. See Maxim 11.

---------------------------------------------------------------------------------------------
Maxims of Maximally Efficient SAS Programmers
Moderator
Posts: 238

Re: Macro modify macro variable value

[ Edited ]

Ok, to just to be clear what you are trying to achieve:

 

  • You have a macro variable P containing a date-formatted value (e.g, 01JAN2017)
  • You have another macro variable D, which may contain a number, a missing (period) or be null.
  • If D is a number, it represents a number of months.
  • If D contains a number, you want to adjust the date value of P by the number of months in D.

So how to check what's in D.. I used the ANYDIGIT() function.. The only fiddly bit was having nested %SYSFUNC() macro functions in the final calculation..

 

%macro MyAdjust(P_Old,D);
  %local P_New;
  %if %sysfunc(anydigit(%str(&d))) %then %let P_New = %sysfunc(intnx(month,%sysfunc(today()),&D.-1,BEGINNING),date9.);
  %put P_Old:&P_Old P_New:&P_New;
%mend;
%MyAdjust(01JAN2017,1); %MyAdjust(01JAN2017,0); %MyAdjust(01JAN2017,12); %MyAdjust(01JAN2017,.); %MyAdjust(01JAN2017,);
P_Old:01JAN2017 P_New:01APR2017
P_Old:01JAN2017 P_New:01MAR2017
P_Old:01JAN2017 P_New:01MAR2018
P_Old:01JAN2017 P_New:
P_Old:01JAN2017 P_New:

 

It just won't work for negative values of D because the negative sign counts as non-digit.

Contributor
Posts: 41

Re: Macro modify macro variable value

Many thanks Andrew,

 

That is what I need.

 

But unfortunately D is almost everytime negative :-(

Do you know how could I do to manage it?

Super User
Posts: 6,936

Re: Macro modify macro variable value

I found this

%let P = %sysfunc(inputn(%sysfunc(putn(%sysfunc(intnx(month,%sysfunc(today()),&D.-1,B)),z6.)),DDMMYYN10));

in my mailbox.

Apart from the fact that it creates a raw value instead of a formatted date (which was expected), it looks like a serious attempt of someone who gets a kick out of hurting him/herself.

It violates several Maxims, notably Maxim 12 and parts of Maxim 11.

It is a bear to type correctly (at which it failed anyway), is hard to read for the next maintainer, and hard to debug.

Instead do

data _null_;
mydate = intnx(month,today(),&D.-1,"b");
call symputx('P',put(mydate,best.),'g');
run;

and use macro variable P directly, without "&P."d. (where somedate <= &P.)

---------------------------------------------------------------------------------------------
Maxims of Maximally Efficient SAS Programmers
Super User
Posts: 10,500

Re: Macro modify macro variable value

You may also not be testing what you think you are with this line:

%if "&D." ne . %then %do;

 

Please check the log after running this code to see a demonstration.

%macro dummy (d);
%if "&D." ne . %then %do;
   %put D was &d when not equal to .;
%end;
%else %do;
   %put D was &d when equal to .;
%end;%mend;

%dummy(d);
%dummy( );
%dummy(.);

%macro dummy2 (d);
%if &D. ne . %then %do;
   %put D was &d when not equal to .;
%end;
%else %do;
   %put D was &d when equal to .;
%end;
%mend;

%dummy2(d);
%dummy2( );
%dummy2(.);
Ask a Question
Discussion stats
  • 7 replies
  • 175 views
  • 2 likes
  • 5 in conversation