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
SAS Innovate 2025 is scheduled for May 6-9 in Orlando, FL. Sign up to be first to learn about the agenda and registration!
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.
Ready to level-up your skills? Choose your own adventure.