Hi!
I would like some help trouble shooting a macro. I found this macro online for range checking my variables. I know there are a lot of ways to range check, but I am hoping to be abl eto build a spreadsheet to not values outside of my acceptable ranges. This one seems to work with that concepts, but I cannot get the macro to work with my sample data. I've also attached the pdf with the macro explained by the author. Any help is greatly appreciated!!
data rangetbl;
input @1 errorid $2.
@3 errorvar $12.
@15 errorsas $40.;
datalines;
1 usmil not(usmil in: (0,1))
2 usciv not(usciv in: (0,1))
3 nonusmil not(nonusmil in: (0,1))
4 nonusciv not(nonusciv in: (0,1))
5 EPW not (EPW in: (0,1))
;
run;
data dataset;
input
@1 medid 3.
@4 usmil 3.
@7 usciv 3.
@10 nonusmil 3.
@13 nonusciv 3.
@16 EPW 3.;
datalines;
1 0 0 1 1 2
2 1 0 1 0 0
3 3 1 2 0 0
4 0 2 1 0 0
;
run;
proc sort data=dataset;
by medid;
run;
data _null_;
set rangetbl end=last;
retain count;
if _n_=1 then count=0;
count=count+1;
call symput ('id'||left (trim(put(count,5.))),
trim (errorid));
call symput ('var'||left (trim(put(count,5.))),
trim (errorvar));
call symput ('code'||left (trim(put(count,5.))),
trim (errorsas));
if last then call symput
('checkct',left(trim(put(count,8.))));
run;
%macro checkvar (id, var, check);
if &check then do;
errorid="&id.";
errorvar="&var.";
errorval=&var;
output;
end;
%mend checkvar;
data error_ds (keep=medid errorid errorvar errorval);
set dataset;
length errorid errorvar $8 errorval 8.;
%macro runcheck;
%do j=1 %to &checkct;
%checkvar (%str (&&id&j),
%str (&&var&j)
%str (&&code&j));
%end;
%mend runcheck;
%runcheck;
run;
Have you looked at the dataset rangetble? There is a chance that the forum has reformatted you text but when I run the code as copy and pasted from the window I get a value of "usmil not" for the first errorvar. I don't have the option expandtabs set and it appears that you have some tabs in the line so that may be a minor bit.
You may also want to consider using some of the features that have appeared since 1999 such as Call symputx which removes leading and trailing blanks of the value so you can reduce the trim(left( code.
Also insted of || there is a nice selection of concatenation functions. and Since Count = _n_ in the data _null_ for creating the macro variables as used why add the variable? That approach might be needed if you were doing something with repeaded values but not here.
data _null_; set work.rangetbl end=last; retain count; if _n_=1 then count=0; count=count+1; call symputx (cats('id',_n_),errorid); call symputx (cats('var',_n_),errorvar); call symputx (cats('code',_n_),errorsas); if last then call symputx('checkct',_n_); run;
If you are interested in seeing what the macro variables look like use: %put _user_; to see all of your created variables in the current scope.
Also when you do this:
data error_ds (keep=medid errorid errorvar errorval); set dataset; length errorid errorvar $8 errorval 8.; %macro runcheck; /* <= %macro ends the previously started data set*/ %do j=1 %to &checkct; %checkvar (%str (&&id&j), %str (&&var&j) /*<=missing ,*/ %str (&&code&j)); %end; %mend runcheck;
the macro definition ends the data step as a boundary like a Run statement or a Proc.
Define the macro before the data step that wants to use it. AND heres likely the fatal part: you are missing a , after the VAR parameter call to %checkvar
Try
%macro runcheck; %do j=1 %to &checkct; %checkvar (%str (&&id&j), %str (&&var&j), %str (&&code&j)); %end; %mend runcheck; data error_ds (keep=medid errorid errorvar errorval); set dataset; length errorid errorvar $8 errorval 8.; %runcheck; run;
Have you looked at the dataset rangetble? There is a chance that the forum has reformatted you text but when I run the code as copy and pasted from the window I get a value of "usmil not" for the first errorvar. I don't have the option expandtabs set and it appears that you have some tabs in the line so that may be a minor bit.
You may also want to consider using some of the features that have appeared since 1999 such as Call symputx which removes leading and trailing blanks of the value so you can reduce the trim(left( code.
Also insted of || there is a nice selection of concatenation functions. and Since Count = _n_ in the data _null_ for creating the macro variables as used why add the variable? That approach might be needed if you were doing something with repeaded values but not here.
data _null_; set work.rangetbl end=last; retain count; if _n_=1 then count=0; count=count+1; call symputx (cats('id',_n_),errorid); call symputx (cats('var',_n_),errorvar); call symputx (cats('code',_n_),errorsas); if last then call symputx('checkct',_n_); run;
If you are interested in seeing what the macro variables look like use: %put _user_; to see all of your created variables in the current scope.
Also when you do this:
data error_ds (keep=medid errorid errorvar errorval); set dataset; length errorid errorvar $8 errorval 8.; %macro runcheck; /* <= %macro ends the previously started data set*/ %do j=1 %to &checkct; %checkvar (%str (&&id&j), %str (&&var&j) /*<=missing ,*/ %str (&&code&j)); %end; %mend runcheck;
the macro definition ends the data step as a boundary like a Run statement or a Proc.
Define the macro before the data step that wants to use it. AND heres likely the fatal part: you are missing a , after the VAR parameter call to %checkvar
Try
%macro runcheck; %do j=1 %to &checkct; %checkvar (%str (&&id&j), %str (&&var&j), %str (&&code&j)); %end; %mend runcheck; data error_ds (keep=medid errorid errorvar errorval); set dataset; length errorid errorvar $8 errorval 8.; %runcheck; run;
Join us for SAS Innovate 2025, our biggest and most exciting global event of the year, in Orlando, FL, from May 6-9. Sign up by March 14 for just $795.
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.