BookmarkSubscribeRSS Feed
🔒 This topic is solved and locked. Need further help from the community? Please sign in and ask a new question.
simple_gearle
Calcite | Level 5

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

 

1 ACCEPTED SOLUTION

Accepted Solutions
SASJedi
SAS Super FREQ

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

Check out my Jedi SAS Tricks for SAS Users

View solution in original post

8 REPLIES 8
SASJedi
SAS Super FREQ

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

Check out my Jedi SAS Tricks for SAS Users
simple_gearle
Calcite | Level 5
Gee whiz, this does the trick. Thanks Mark!
ballardw
Super User

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.

 

simple_gearle
Calcite | Level 5
That is really slick code for getting at all of the data sets in library. I may only need the previous code for getting any temporary datafiles. Thanks for your help!
ballardw
Super User

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.

 

SASJedi
SAS Super FREQ
My pleasure 🙂
Check out my Jedi SAS Tricks for SAS Users
Tom
Super User Tom
Super User

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;
Ron_MacroMaven
Lapis Lazuli | Level 10

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

SAS Innovate 2025: Register Now

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!

How to Concatenate Values

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.

SAS Training: Just a Click Away

 Ready to level-up your skills? Choose your own adventure.

Browse our catalog!

Discussion stats
  • 8 replies
  • 3653 views
  • 0 likes
  • 5 in conversation