Hi,
I have a task where I have to save all Macros and print the list of all those saved macros. In my scenario, I have different '.sas' files for each different macros saved in one folders
For eg. `StoredMacros` is the folder name and `Macro1`, `Macro2`, 'Macro3'..... are macros stored in different files.
With the following code I am saving macros in library:-
libname mylib '/home/folder/StoredMacros/';
options mstored sasmstore=mylib;
Now, I am not sure whether we can store whole folder containing macros. Can we?
Next, I want to have the list of all macros that are stored in library. I have came across some suggestions to use `PROC CATALOG`.
Following is the some code snippets that I have tried to achieve this :-
1)
proc catalog=mylib;
Contents;
run;
quit;
2)
proc sql;
select *
from dictionary.catalogs
where objtype='MACRO' and libname='mylib';
quit;
3)
%put _ALL_;
Output of all these trials, brings list of macros of libraries 'WORK' and 'SASHELP' but not of 'mylib`.
I am sure the trick is very simple but am not able to catch it.
Please feel free to ask any query if I missed any detail in my query.
I would appreciate the help around using PROC CATALOG.
Thank You in Advance!!
Avoid the use of catalogs, they are proprietary binary files formats which are not portable, not open, and if you had to migrate from 32/64bit, very dangerous as there is no migration path other than going back to source. Use plain text files which are open source and portable. It is also then a simple task of listing the contents of listing the contents of a folder.
It doesn't sound like you actually have stored compiled macros. Files with an extension of '.sas' should contain SAS code. They could contain macro definitions, but they could just contain regular SAS programs.
If you have created those files to use as an autocall library then you might want to just assume that the filename matches the name of the macro that the code defines. So you just need to get a list of the filenames.
If they are not maintained as one file per macro definition then you might need to just run the programs to compile the macros and then look at what compiled macros get created in the WORK.SASMACR catalog. (Note if you are using an application server via EG or SAS/studio then the catalog name is slightly different.)
Executing code...
proc sql;
select *
from dictionary.catalogs
where objtype='MACRO'
;
quit;
...will return a list of all compiled macros currently available to you. Macros in SASMSTORE are compiled so they will be in this list.
What this code won't give you:
Macros which are part of the SAS Autocall facility but which haven't been compiled yet. The SAS Autocall Facility allows you to create a search path for macros (via SAS Option SASAUTOS).
If you call a macro in your code then SAS will first search through a few of the in-built places like SASMSTORE and the SAS macro catalogue in work. If it doesn't find the macro there then it will also search through all the destinations listed under option SASAUTOS (and stop as soon as it gets a hit).
SASAUTOS can contain both references to macro catalogues with pre-compiled macros and paths to folders with SAS code. SAS will search for a macro in the sequence how they are listed in SASAUTOS.
If it's a folder path then SAS will search in this folder for a file with the name of the macro - so if you have in your code a macro call like %mymacro() then SAS will search in the folder for a file with name mymacro.sas. If it finds such a file then it will execute the code which will compile the macro into the macro catalog in Work.
You will need to have in this file code which defines the macro - so something like %macro mymacro(); .... %mend; - If you have additional macro definitions in this file then these macros will get compiled as well.
....if you would re-run the query on dictionary.catalogs the newly compiled macro (in the Work macro catalog) would get listed as well.
And now after these lengthy explanations I hope you understand that if you really want a full list of all macros available to you at a specific point in time you need additionally to querying dictionary.catalog also to derive all the paths from SASAUTOS, then traverse through this list and search in all the files in these folders for macro definitions matching the file names containing the macro definition - and then also look for additional macro definitions in these files as these are macros also available to you once you've called the one with the name of the file.
And last but not least:
I principally agree with @RW9 that not pre-compiling macros avoids a lot of issues BUT: When performance is really important (seconds) then precompiling macros can become necessary. Not because compilation of a macro takes a lot of time but because creating the directory listings searching for the .sas file can be slow. I believe it was @SASKiwi who posted quite a while a ago an example demonstrating that it took something like 10 seconds to find a not yet compiled macro on the file system.
I know it's been more than a year, but this might still help someone so here goes. Setting aside questions of whether to pre-compile macros or not, the second example of OP's code will work with one small change:
proc sql;
select *
from dictionary.catalogs
where objtype='MACRO' and libname='mylib';
quit;
In dictionary.catalogs, libnames are all caps, and this is a case sensitive match. Change the where clause to:
where objtype='MACRO' and libname='MYLIB';
and you'll get the desired listing of your saved macros.
Hi,
If you stored macro in this folder:
libname mylib '/home/folder/StoredMacros/';
You can recall all macro saved
options mstored sasmstore=mylib;
With this proceduce you can print a list of macros from catalog:
proc catalog CATALOG=mylib.sasmacr ;
Contents;
run;
quit;
Another option to get a list of macros using a filter on the dictionary alfter calling stored macro:
proc sql;
select *
from dictionary.catalogs
where objtype='MACRO' and libname='MYLIB';
quit;
Regards,
@Luisfco88 wrote:
Hi,
If you stored macro in this folder:
libname mylib '/home/folder/StoredMacros/';
You can recall all macro saved
options mstored sasmstore=mylib;With this proceduce you can print a list of macros from catalog:
proc catalog CATALOG=mylib.sasmacr ; Contents; run; quit;
Another option to get a list of macros using a filter on the dictionary alfter calling stored macro:
proc sql; select * from dictionary.catalogs where objtype='MACRO' and libname='MYLIB'; quit;
Regards,
This corrects some of the problems with the earlier answers.
Let's spell them out.
1) LIBNAME variable in the DICTIONARY tables is always in uppercase.
2) If you are looking for the compiled macros that are currently available you need to check the setting of the SASMSTORE system option. A query against DICTIONARY.CATALOGS without limiting the results to those found in the catalog that will actually be used by SASMSTORE could return the names of macros that are compiled but not current discoverable.
Are you ready for the spotlight? We're accepting content ideas for SAS Innovate 2025 to be held May 6-9 in Orlando, FL. The call is open until September 16. Read more here about why you should contribute and what is in it for you!
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.
Select SAS Training centers are offering in-person courses. View upcoming courses for: