I would like to create a Macro that can take a variable number of arguments.
Please note that the psuedo-program that I write below perhaps could bypass the need for variable number of arguments, but the point with the programe is to demonstrate my need (In reality it is a more complex program that I am writing).
So the following program shows that I would like to create a function that can take arbitrary number of arguments and then sum them.
%Macro MyMacro(X1, X2, + ...);
sum = X1 + X2 + ... ;
%mend;
If I knew that I would like to sum only two numbers, it would be very easy:
%Macro MyMacro(X1, X2); sum = X1 + X2; %mend;
But I don't know how many numbers I want to sum (it depends), so the question is, how could I allow for an arbitrary number of arguments?
@SasStatistics wrote:
I would like to create a Macro that can take a variable number of arguments.
Please note that the psuedo-program that I write below perhaps could bypass the need for variable number of arguments, but the point with the programe is to demonstrate my need (In reality it is a more complex program that I am writing).
So the following program shows that I would like to create a function that can take arbitrary number of arguments and then sum them.%Macro MyMacro(X1, X2, + ...); sum = X1 + X2 + ... ; %mend;
If I knew that I would like to sum only two numbers, it would be very easy:
%Macro MyMacro(X1, X2); sum = X1 + X2; %mend;
But I don't know how many numbers I want to sum (it depends), so the question is, how could I allow for an arbitrary number of arguments?
This isn't a situation where you need a variable number of arguments. It is a situation where you need one argument that can have a different number of values each time you run the macro.
%Macro MyMacro(X);
%let x=%sysfunc(translate(&x,%str(+),%str( )));
sum = &x;
%mend;
options mprint;
data want;
%mymacro(2 4 6)
run;
data want2;
%mymacro(2 4 6 8 10 12 14)
run;
Or even more general solution
%Macro MyMacro(X);
%let x=%sysfunc(translate(&x,%str(+),%str( )));
&x
%mend;
options mprint;
data want;
sum1=%mymacro(2 4 6);
sum2=%mymacro(2 4 6 8 10 12 14);
run;
@SasStatistics wrote:
I would like to create a Macro that can take a variable number of arguments.
Please note that the psuedo-program that I write below perhaps could bypass the need for variable number of arguments, but the point with the programe is to demonstrate my need (In reality it is a more complex program that I am writing).
So the following program shows that I would like to create a function that can take arbitrary number of arguments and then sum them.%Macro MyMacro(X1, X2, + ...); sum = X1 + X2 + ... ; %mend;
If I knew that I would like to sum only two numbers, it would be very easy:
%Macro MyMacro(X1, X2); sum = X1 + X2; %mend;
But I don't know how many numbers I want to sum (it depends), so the question is, how could I allow for an arbitrary number of arguments?
This isn't a situation where you need a variable number of arguments. It is a situation where you need one argument that can have a different number of values each time you run the macro.
%Macro MyMacro(X);
%let x=%sysfunc(translate(&x,%str(+),%str( )));
sum = &x;
%mend;
options mprint;
data want;
%mymacro(2 4 6)
run;
data want2;
%mymacro(2 4 6 8 10 12 14)
run;
Or even more general solution
%Macro MyMacro(X);
%let x=%sysfunc(translate(&x,%str(+),%str( )));
&x
%mend;
options mprint;
data want;
sum1=%mymacro(2 4 6);
sum2=%mymacro(2 4 6 8 10 12 14);
run;
Thanks @PaigeMiller, what my actual function need is to be able to put in one argument with several table names (in retrospect, my pseudo program did not catch what I wanted i realize...).
So for instance argument x could look like:
x = [Table1, Table2, Table3, ...].
Something clever exists for this?
@SasStatistics wrote:
Thanks @PaigeMiller, what my actual function need is to be able to put in one argument with several table names (in retrospect, my pseudo program did not catch what I wanted i realize...).
So for instance argument x could look like:
x = [Table1, Table2, Table3, ...].
Something clever exists for this?
What are you going to do with the several table names??
Again, I don't think you need several macro arguments, I think you need one argument that can contain several table names ... but until I know what you intend to do with the table names, I can't be sure.
" I think you need one argument that can contain several table names", exactly what I mean (and think I wrote in the reply?).
The function I would like to create will from each table name extract all the columns in the table and print it out so the user can get an overview.
Thanks @PaigeMiller .
@SasStatistics wrote:
The function I would like to create will from each table name extract all the columns in the table.
Extract all the columns? Or extract all the column names?
Assuming you mean column names, here is some code that also uses the %qlist macro (at https://github.com/sasutils/macros/blob/master/qlist.sas).
%macro colnames(arg);
%let q_arg=%qlist(&arg);
proc sql;
create table colnames as select libname,memname,name
from dictionary.columns where upcase(memname) in %upcase(&q_arg);
quit;
%mend;
%colnames(cars want)
I'm sure there are ways to do this without %qlist, but I'm so used to using %qlist that I don't ever bother to try to figure out other ways to do it without %qlist.
I wanted to extract all column names.
Running the code supplied:
%macro colnames(arg);
%let q_arg=%qlist(&arg);
proc sql;
create table colnames as select libname,memname,name
from dictionary.columns where upcase(memname) in %upcase(&q_arg);
quit;
%mend;
%colnames(cars want)
yields the following error:
WARNING: Apparent invocation of macro QLIST not resolved. WARNING: Apparent invocation of macro QLIST not resolved. NOTE: Line generated by the macro function "UPCASE". 36 %QLIST(CARS WANT) _ 22 76 WARNING: Apparent invocation of macro QLIST not resolved. ERROR 22-322: Syntax error, expecting one of the following: (, SELECT. ERROR 76-322: Syntax error, statement will be ignored.
You need to define macros before using them (or at least same them in your autocall library so SAS can find them to autocompile).
Here is a QLIST macro that would probably work with the program.
https://github.com/sasutils/macros/blob/master/qlist.sas
You have to place the code for %qlist in your code before %colnames, and then execute both. I put %qlist (and many other useful macros) in my AUTOCALL library, so I don't need to copy and paste the code for the %qlist macro every time I want to use it. The AUTOCALL library is in my AUTOEXEC so every time I launch SAS, these macros are made available to me. If you are going to be writing a lot of macros, you should set up an AUTOCALL library. Here is the command in my AUTOEXEC file and all of my utility macros are stored in that folder..
options sasautos=(sasautos 'myserver\MillerP\Macros');
@SasStatistics wrote:
If the function I am using will be used by other people, what would be best then? To include the code for the %qlist macro in my macro?
The answer is a great big "it depends" and also, as I'm sure you know, there are "many ways to skin a cat" as the expression goes (although I can't verify that the expression is true as I have never tried doing that).
Certainly, you can place %qlist in the same file as %mymacro and named mymacro.sas (again, better names are needed) and then distribute this SAS file to whomever you'd like (or use the code from @Tom which doesn't require %qlist).
If everyone can access your server where mymacro.sas is stored and where qlist.sas is stored as separate files, then they can add this as the first line of their code and then suddenly, like magic, they can access both qlist.sas and mymacro.sas and any other macro in the indicated folder, and now %qlist does not have to be defined inside mymacro.sas
options append=(sasautos="myserver\MillerP\Macros");
The benefit of doing it this way on a server that everyone can access is that if you fix a bug or add a new feature to your macro, everyone using it this way gets the changes instantaneously, with zero effort on their part. If you have to include %qlist in the file and then perhaps e-mail it to others, then when you update your copy, the recipients of the e-mail still have the old version.
There is also a way to call the qlist.sas file directly from github in your program and so you just need one command in your code to access %qlist. Not everyone can do this, there are some restrictions on what external files I can access from my company computer becuase of the company firewall; and so I don't know the command, but I'm sure others do. Again, it depends on if this will work behind your company's firewall.
Haha I am sure there is although I have not tried it either... 😉
"If everyone can access your server where mymacro.sas is stored and where qlist.sas is stored as separate files, then they can add this as the first line of their code and then suddenly, like magic, they can access both qlist.sas and mymacro.sas and any other macro in the indicated folder, and now %qlist does not have to be defined inside mymacro.sas"
This is the alternative I will go for. What do you mean by: "then they can add this as the first line of their"?
The first line of the program they write to use your macros should be the OPTIONS statement I provided.
@SasStatistics wrote:
" I think you need one argument that can contain several table names", exactly what I mean (and think I wrote in the reply?).
The function I would like to create will from each table name extract all the columns in the table and print it out so the user can get an overview.
Thanks @PaigeMiller .
Supply the list of names as the value of one parameter.
%macro mymacro(members);
proc print data=sashelp.vcolumn;
where findw("&members",memname,' ','it');
var libname memname varnum name type length format label;
run;
%mend mymacro;
%mymacro(class cars)
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.