I'm trying to write where any given macro variable can be numeric or character as the list of possible input value could be any integer, possibly preceded or followed by a character (i.ee = -1, 0, 1, d1, w9e), but something is off. See below for the simplified code:
Checking if variable is integer: %macro isnum (mv); %eval(not %sysfunc(verify(&mv,-0123456789))); %mend isnum; %macro DefineDate(dt1,dt2,dt3); ... %do i = 1 %to 3; %put Test dt&i. = &&dt&i.; %if %length(&&dt&i.) ne 0 %then %do; %put Variable dt&i. = &&dt&i.; %if %isnum(&&dt&i.) = 1 %then %do; %put dt&i. isnum successful; %end; %else %do; %put dt&i. isnum did not run; %put dt&i. numericity is %isnum(&&dt&i.); %end; %else %put dt&i. does not exist; %end; %mend; %DefineDate(dm1,0)
The output to the log is:
Test dt1 = dm1
Variable dt1 = dm1
dt1 isnum did not run
dt1 numericity is 0;
Test dt2 = 0
Variable dt2 = 0
dt2 isnum did not run
dt2 numericity is 1;
Test dt3 =
dt3 does not exist
I can't understand why I can't get the %IF conditional to run in the second step, despite it returning 1 in the identical put statement.
Thank you
I just been able to solve it!
%if %sysfunc(prxmatch('^-?\d+$',&&dt&i.)) = 1 %then %do;
This did the trick for me and should be easily changable should the requirements someday change to include decimals 🙂
In my opinion @Reeza is bang on target with notdigit being the sweetest. However, You could use %sysevalf to evaluate to a Boolean result. I learned that from Guru of Gurus @data_null__ . Little too late and tired in Chicago night, but I hope I comprehended the topic.
Ok, I'll retry and update in a bit. Thanks for your time, much appreciated!
a simple test-log report
2078 %put %sysfunc(notdigit(a123));
1
2081 %put %sysfunc(notdigit(123));
0
brilliant question and %sysevalf has the answer
log:
%put %SYSEVALF( %sysfunc(notdigit(123.22)) , boolean );
1
I think my usage is wrong but we are close
The %isnum macro also returned 1, despite the %IF not returning true for checking = 1
%put dt&i. numericity is %isnum(&&dt&i.)
This returns dt2 numericity is 1, so I got that far too.
I also tried NOTDIGIT and I got this in the log:
ERROR: Required operator not found in expression: notdigit(&&dt&i.) = 0 ERROR: The macro DEFINEDATE will stop executing.
I think I'll give up on these methods for now and try to use prxmatch for a bit. This is breaking my mind why it returns 1 in a %PUT, but can't evaluate %IF %ISNUM(&&dt&i.) = 1 as true at the same time with all other proposed solutions giving me errors.
I will test tomorrow morning and get to the bottom of it but I'm more than 100% certain , somebody else will give you the much needed solution while my night passes by sleeping. Hang in there
I just been able to solve it!
%if %sysfunc(prxmatch('^-?\d+$',&&dt&i.)) = 1 %then %do;
This did the trick for me and should be easily changable should the requirements someday change to include decimals 🙂
very nice
@WimB wrote:
This did the trick for me and should be easily changable should the requirements someday change to include decimals 🙂
For more general types of numeric values (including decimals and scientific notation) there's also the %DATATYP Autocall Macro.
The real problem is that you included a semi-colon in your macro "function". A macro that only generates part of a statement cannot generate a semi-colon because that will prematurely terminate any statement that you try to use it in.
1 %macro isnum (mv); 2 %eval(not %sysfunc(verify(%superq(mv),-0123456789))) 3 %mend isnum; 4 5 %put %isnum(fred); 0 6 %put %isnum(123); 1 7 %put %isnum(-1.2.3); 0 8 %put %isnum(); 1
Are you ready for the spotlight? We're accepting content ideas for SAS Innovate 2025 to be held May 6-9 in Orlando, FL. The call is open until September 25. Read more here about why you should contribute and what is in it for you!
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.