There are a number of doing this in SAS.
1) The CALL EXECUTE strategy is good. However, you should be aware that CALL EXECUTE can behave oddly at times. Be VERY careful about the use of RUN in all PROC and DATA steps inside the macro being CALL EXECUTE-processed.
2) When writing the CALL EXECUTE statement, I NEVER just put the variable name, which allows SAS to convert numeric variables into character. I ALWAYS format variables.
It is much better to do something like some have suggested but improved slightly:
DATA _NULL_;
SET SOURCE;
STRNG=CATS('%_mymac(_a="' , TRIM(LEFT(STRA)), '",_b=' ,
TRIM(LEFT(PUT(HEIGHT,4.1))) , ');');
CALL EXECUTE(STRNG);
RUN;
Using the explicit PUT statement ensures that you control the exact formatting, not SAS. Default formats can be problematical.
2) Many persons have suggested ALWAYS enclosing the CALL EXECUTE information in a %nrstr to ensure that the timing of the CALL EXECUTE process is correct.
DATA _NULL_;
SET SOURCE;
STRNG=CATS('%_mymac(_a="' , TRIM(LEFT(STRA)), '",_b=' ,
TRIM(LEFT(PUT(HEIGHT,4.1))) , ');');
CALL EXECUTE(%nrstr(STRNG));
RUN;
4) Writing out macro calls to a file can work too, but is clunky. It does give you the opportunity of looking at the macro code, which can be useful at times.
5) You can use "macro arrays". Here is a sketch:
%macro _iter;
DATA _NULL_;
SET SOURCE;
RETAIN CX 0;
CX+1;
VX=COMPRESS(PUT(CX,3.));
CALL SYMPUT("_pxa"||VX,TRIM(LEFT(NAME)));
CALL SYMPUT("_pxb"||VX,TRIM(LEFT(PUT(HEIGHT,5.1))));
CALL SYMPUT("_cx",VX);
RUN;
%do _i=1 %to &_cx;
%_mymac(_name=&&_pxa&_i,_height=&&_pxb&_i)
%end;
%mend _iter;
%_iter
These are embedded in a macro, since macro loops cannot run in plain code. The use of the TRIM and LEFT commands removes leading and trailing blanks, which are usually not an issue but can become a problem sometimes. It's a little trouble, but only a little.
6) With a small amount of work writing arrays, the CALL SYMPUT commands can be set up as arrays to process up an unlimited number of variables.