BookmarkSubscribeRSS Feed
fabdu92
Obsidian | Level 7

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. 🙂

7 REPLIES 7
AndrewHowell
Moderator

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= ...
RW9
Diamond | Level 26 RW9
Diamond | Level 26

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. 

Kurt_Bremser
Super User

&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.

AndrewHowell
Moderator

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.

fabdu92
Obsidian | Level 7

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?

Kurt_Bremser
Super User

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.)

ballardw
Super User

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(.);

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
  • 7 replies
  • 6071 views
  • 2 likes
  • 5 in conversation