Hi sas support community i am very poor in sas macros can anyone sugest how improve macro coding?
My fun answer of the day: Find Ron Fehd, spend a whole week with him, and you, too will become a Macro Expert.
Hi and welcome to the SAS Communities 🙂
Lots of learning material out there. But the best is probably the Documentation itself:
The first (and really essential, important and absolutely necessary) step in good macro coding: achieve proficiency in coding without using macros.
The macro preprocessor is a code generator, and you'll only be able to use it properly when you have very good knowledge of the code you will be creating with the macro.
And very often you will find that proper knowledge of the non-macro tools leads to the gist of Maxim 11: A Macro is not Needed.
90% of the problems with macros we encounter here on the communities comes from premature tinkering with macros and trying to solve data issues with the wrong tool.
As others have indicated, macros should be a last resort.
Assuming you already know the following well:
Some good resources:
https://stats.idre.ucla.edu/sas/seminars/sas-macros-introduction/
Macro appendix, in the documentation has a set of good examples:
My short tutorial on creating a macro:
https://github.com/statgeek/SAS-Tutorials/blob/master/Turning%20a%20program%20into%20a%20macro.md
One general premise of writing a macro - first make sure you have working code that solves the situation for a base case and then generalize it. If you skip this step, you run the risk of spending hours debugging.
Hello,
You can execute the following program and read the log to have an illustration of
the main concepts of SAS macro programming.
/* Macro quick tutorial */
/* Note: SAS macros are used to generate SAS code and should not be used for processing data */
options mprint mlogic symbolgen; /* Add useful informations in the log */
%let mv=10; /* a macro variable is initialized with %let */
/* &<macrovariable>. is replaced at compile time by its value */
%put &mv.; /* 10 displayed in the log */
data ds&mv.; /* data ds10; */
set sashelp.class;
run;
%let mv2=&mv.+1; /* 10+1 not 11 => only text substition */
%put &mv2.; /* 10+1 displayed in the log */
data ds&mv2.; /* data ds10+1; => ERROR */
set sashelp.class;
run;
%let mv3=%eval(&mv.+1); /* 11 */
%put &mv3.;
/* A macro variable can hold the name of another macro variable */
%let x=5;
%let mvname=x;
/* During the resolution, two consecutive ampersands are resolved in a single ampersand */
%put &mvname.; /* x */
%put &&mvname.; /* x ((&&)mvname. => &mvname. => x) */
%put &&&mvname.; /* 5 ((&&)(&mvname.) => &x. => 5)*/
data _NULL_;
set sashelp.class;
/* Creates a macrovariable from a dataset column */
/* The instruction is executed for each row of data */
call symputx("name", name);
%put &name.; /* &name. will only be available at the end of the datastep */
/* => WARNING if the macrovariable does not exist previous to */
/* the data step */
/* otherwise, its value before the data step. */
run;
%put &name.; /* William (last observation of sashelp.class) */
data _NULL_;
set sashelp.class;
call symputx(cats("name",_N_), name);
run;
%put &name1. &name2. &name3.; /* Alice Barbara Carol */
/* Affectation of macrovariables to dataset columns */
data macro;
length will name $32.;
will=symget("name"); /* William */
will2="&name."; /* William */
will3='&name.'; /* &name. => no resolution with single quotes */
x=symgetn("x"); /* 5 */
do _N_=1 to countw("&names.");
name=symget(cats("name",_N_)); /* Alice, Barbara, Carol, ... William */
output;
end;
run;
/* Create macrovariables from dataset columns with proc sql */
proc sql noprint;
SELECT name, name
INTO :name, :names SEPARATED BY ' '
FROM sashelp.class;
quit;
%put &name.; /* Alice */
%put &names.; /* Alice Barbara Carol ... Thomas William */
/* Macro functions are necessary for conditional branching, loops */
/* They can be used for repetitive tasks to avoid replicating large */
/* chunks of code. */
%macro f(pos, kw=default, kw2=);
/* pos : positional argument */
/* kw, kw2 : keyword parameters */
/* positional parameters must apperar before keyword parameters */
%if &pos.=1 %then %do;
%put OK;
%end;
%else %do;
%put KO;
%end;
%put &kw. &kw2;
%mend; /* end of the macro function definition */
%f(1) /* OK default */
%f(2, kw2=hello) /* KO default hello */
%f(2, kw=foo) /* KO foo */
%f(kw=bar) /* KO bar */
%f(kw=bar,pos=0) /* KO bar => positional parameters can also be called by name */
/* Usage of macro loops */
%macro f2(ds, out);
%do i=1 %to 5;
data &out.&i.;
row=&i.;
set &ds. point=row;
output; stop;
run;
/* Loops can be used to create indexed macrovariables */
%let x&i.=&i.; /* x1=1, x2=2, ..., x5=5 */
%put &&x&i.; /* 1, 2, 3, 4, 5 ((&&)(x&i). => &x1. => 1 */
%end;
%mend;
%f2(sashelp.class, student) /* datasets student1 (Alice), student2 (Barbara) */
/* Scope */
%let j=1; /* defined outside macro => global scope */
%macro a;
%do i=1 %to 5;
%put &i.;
%end;
%mend;
%macro main;
/* The same counter name (i) is used in macro main and macro a */
%do i=1 %to 2;
%a;
%end;
%let j=2; /* Modifies the global macro variable j */
%mend;
%main /* 1 2 3 4 5 (the value of i in macro a replaced the one computed in macro main) */
/* => Only one iteration of the loop in main */
%put &j.; /* 2 (modified by the macro) */
%macro b;
%local i; /* i is now a macrovariable specific to the macro b */
%do i=1 %to 5;
%put &i.;
%end;
%mend;
%macro main2;
%local j;
%do i=1 %to 2;
%b;
%end;
%let j=5;
%mend;
%main2 /* 1 2 3 4 5 1 2 3 4 5 */
%put &j.; /* 2 (the global variable value has not been replaced) */
Edit : Added @Tom example of macro call with names positional argument.
I would add an example in your block of example macro calls where you call the positional parameter by name. That is a very nice usability feature of SAS macro calls that other languages often lack.
%f(kw=bar,pos=0) /* KO bar */
My fun answer of the day: Find Ron Fehd, spend a whole week with him, and you, too will become a Macro Expert.
SAS Innovate 2025 is scheduled for May 6-9 in Orlando, FL. Sign up to be first to learn about the agenda and registration!
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.