04-26-2017 07:22 AM
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.
04-26-2017 07:39 AM
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.
04-26-2017 07:41 AM
&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
(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.
04-26-2017 09:45 AM - edited 04-26-2017 09:50 AM
Ok, to just to be clear what you are trying to achieve:
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,);
It just won't work for negative values of D because the negative sign counts as non-digit.
04-27-2017 02:27 AM
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.
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.)
04-26-2017 11:03 AM
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(.);