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.
... View more