DATA Step, Macro, Functions and more

Macro using Symputx

Accepted Solution Solved
Reply
Occasional Contributor
Posts: 6
Accepted Solution

Macro using Symputx

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
Solution
‎03-17-2016 01:49 PM
SAS Employee
Posts: 104

Re: Macro using Symputx

[ Edited ]
Posted in reply to simple_gearle

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

View solution in original post


All Replies
Solution
‎03-17-2016 01:49 PM
SAS Employee
Posts: 104

Re: Macro using Symputx

[ Edited ]
Posted in reply to simple_gearle

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

Occasional Contributor
Posts: 6

Re: Macro using Symputx

Gee whiz, this does the trick. Thanks Mark!
Super User
Posts: 11,343

Re: Macro using Symputx

Posted in reply to simple_gearle

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.

 

Occasional Contributor
Posts: 6

Re: Macro using Symputx

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!
Super User
Posts: 11,343

Re: Macro using Symputx

Posted in reply to simple_gearle

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.

 

SAS Employee
Posts: 104

Re: Macro using Symputx

Posted in reply to simple_gearle
My pleasure :-)
Super User
Super User
Posts: 7,039

Re: Macro using Symputx

Posted in reply to simple_gearle

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;
Regular Contributor
Posts: 227

Re: Macro using Symputx

Posted in reply to simple_gearle

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

☑ This topic is solved.

Need further help from the community? Please ask a new question.

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