%macro foreach(dset,var,macro=doit,debug=0,maxvals=999999,missvals=0,format=$); %*--This utility macro will invoke the macro specified by the macro parm (by default - the doit macro), passing it a single positional parm. It will do this for each distinct value of &var in the sas dataset &dset. So, for example, if I invoke with: %foreach(mycds,cdtitle,macro=cdmac) It will generate invocations of the cdmac macro, one invocation for each distinct value of cdtitle in the dataset mycds. The format parm specified what format code, if any, is to be used when extracting distinct values. The default value works only with character variables and is a generic character format ($.) If the variable has a user-defined format code associcated with it, that format does not get used when the default value is specified. If you want the formatted values, then you can specify the format explicitly, i.e. format=$myfmat. or, if that format is already associated with the variable on the dataset, by setting format to a null value. Then the values that will be passed as the single parms will be formatted values rather than original values as they appear in the dataset. The values of the parameters dset and var are copied to global macro variables _forvar and _fordset so that these can be used within the doit macro (or whatever name you specify for macro). John Blodgett, July, 2002. --; %if &debug %then %do; %put foreach macro invoked with parms: ; %put dset (dataset where var values are found)= &dset; %put var (variable in &dset whose distinct values will be passed to ¯o)= &var; %put macro (SAS macro with single positional parm to be invoked once for each distinct value of &var) = ¯o; %end; %local _vals; %global _forvar; %let _forvar=&var; %*<--so the macro can access this and know which variable--; %global _fordset; %let _fordset=&dset; %*--if format parm is not null and does not end with a period, add one--; %if %superq(format) ne %str() and %qsubstr(&format,%length(&format),1) ne %str(.) %then %let format=&format%str(.); %local format_spec; %if %superq(format) ne %str() %then %let format_spec= %str(format=)%unquote(&format) ; proc sql noprint; select distinct &var &format_spec into :_vals separated by '^' from &dset %if &missvals=0 %then %str( where &var is not missing ); ; quit; %local i val; %let i=1; %let val=%scan(&_vals,&i,%str(^)); %do %while (&val ne %str() and (&i le &maxvals) ); %if &debug %then %put ****Will invoke ¯o with parm value: &val ****; %¯o(&val) %let i=%eval(&i+1); %let val=%scan(&_vals,&i,%str(^)); %end; %mend foreach;