- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content
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
Accepted Solutions
- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content
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
- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content
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
- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content
- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content
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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content
- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content
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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content
- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content
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;
- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content
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