Hello,
I have what I thought was a simple macro using SYMPUTX to assign the number of observations of a dataset to a macro variable. My intent is to use this macro to get the observations numbers of multiple datasets that are manipulated in various SAS programs, the resulting dataset would be printed for QC check and documentation.
Here is the code. In this example, I am using %put to demonstrate the error.
%macro ObsNumber(file,Var_Name);
data _NULL_;
if 0 then set &File. nobs=n;
call symputx(&Var_Name.,n);
stop;
run;
%mend ObsNumber;
%ObsNumber(Sashelp.Class, 'Nrows_Class');
%put &Nrows_Class;
The log reads
WARNING: Apparent symbolic reference NROWS not resolved.
&Nrows
However, If I pull the code out of the macro and run it with file and var_name manually entered, the log states 19 as expected.
data _NULL_;
if 0 then set Sashelp.Class nobs=n;
call symputx('Nrows',n);
stop;
run;
%put &Nrows;
Any thoughts on a solution would be much appreciated.
Thanks, Andrea
The problem is that the macro variable Nrows_class has local scope. Once the macro stops executing, the local symbol table is destroyed, and the value is no longer available. If your %put was INSIDE the macro, you could still access the Nrows_class variable:
%macro ObsNumber(file,Var_Name); data _NULL_; if 0 then set &File. nobs=n; call symputx(&Var_Name.,n); stop; run; %put &Nrows_Class; %mend ObsNumber; %ObsNumber(Sashelp.Class, 'Nrows_Class');
produces the result you want in the log: 19.
If you need to access this value after the macro stops running, just use CALL SYMPUTX's third parameter to create the value in the global symbol table instead:
%macro ObsNumber(file,Var_Name); data _NULL_; if 0 then set &File. nobs=n; call symputx(&Var_Name.,n,'G'); stop; run; %mend ObsNumber; %ObsNumber(Sashelp.Class, 'Nrows_Class'); %put &Nrows_Class;
And now you can access the value after the macros stops executing.
Hope this helps 🙂
Mark
The problem is that the macro variable Nrows_class has local scope. Once the macro stops executing, the local symbol table is destroyed, and the value is no longer available. If your %put was INSIDE the macro, you could still access the Nrows_class variable:
%macro ObsNumber(file,Var_Name); data _NULL_; if 0 then set &File. nobs=n; call symputx(&Var_Name.,n); stop; run; %put &Nrows_Class; %mend ObsNumber; %ObsNumber(Sashelp.Class, 'Nrows_Class');
produces the result you want in the log: 19.
If you need to access this value after the macro stops running, just use CALL SYMPUTX's third parameter to create the value in the global symbol table instead:
%macro ObsNumber(file,Var_Name); data _NULL_; if 0 then set &File. nobs=n; call symputx(&Var_Name.,n,'G'); stop; run; %mend ObsNumber; %ObsNumber(Sashelp.Class, 'Nrows_Class'); %put &Nrows_Class;
And now you can access the value after the macros stops executing.
Hope this helps 🙂
Mark
Another option since you say you are looking printing the number would be to use Dictionary.Tables or sashelp.vtable with a where clause for the library and data set names and print the information directly.
proc sql;
title "SASHELP data sets starting with C";
select memname, nobs
from dictionary.tables
where libname='SASHELP' and memtype='DATA' and
substr(memname,1,1)='C'
;
quit;
even easier is all the datasets in a library or using IN operator a list of libraries. Or have a data set with the libname and member name and use a join to get the information. Note that lots of other information is available such as numbers of variable, size, dates, sorting, encoding.
Since temporary sets go into WORK, the use WORK for the library name and the example code will get sizes for your temp sets as well.
A couple of other coding points on your code.
1) Pass the name of the macro variable without the quotes around it. You can use double quotes in the CALL SYMPUTX() statement to expand the macro variable's value as the name of the target macro variable.
%macro ObsNumber(file,Var_Name);
...
call symputx("&Var_Name",n);
...
%mend ObsNumber;
%ObsNumber(Sashelp.Class, Nrows_Class);
%put &Nrows_Class;
2) You don't need the IF 0 trick since you have already added a hard coded STOP statement to your data step. Just change the order of the statements.
data _null_;
call symputx("&Var_Name",n);
stop;
set &File. nobs=n;
run;
You can avoid running a data step to get this information
by using sysfunc to call scl functions.
http://www.sascommunity.org/wiki/Macro_nobs
Ron Fehd macro maven
Registration is now open for SAS Innovate 2025 , our biggest and most exciting global event of the year! Join us in Orlando, FL, May 6-9.
Sign up by Dec. 31 to get the 2024 rate of just $495.
Register now!
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.