- The argument to DOSUB is a fileref that point to the code to be executed.
- The argument to DOSUBL is the line (or lines) of code to be executed.
- Determine how many observations there are in the input data set.
- Use a macro to loop from 1 to the number of observations and do the following in each iteration
- Read the ith observation
- Load the values of the needed variables into macro variables
- Invoke PROC STREAM to process a SAS Server Page that references the macro variables in the text of the letter
/* map the value of sex to daughter/son */
value $gender 'F' = 'daughter'
'M' = 'son'
/* associate formats with sex and age */
format sex $gender. age words.;
/* create macro vars from the data step vars */
/* vvalue uses the formatted value */
/* define the code to run for each observation */
code = 'filename letter "&root\letters\&name..html" '
||'proc stream outfile=letter quoting=both; '
||'&streamdelim; %include srvrpgs(class.html); '
/* run the code */
rc = dosubl(code);
Each execution of the DATA step invokes PROC STREAM to generated the desired letter.
CALL EXECUTE vs DOSUB and DOSUBLLike CALL EXECUTE, the DOSUB and DOSUBL functions allow you to generate code to be executed. However, unlike CALL EXECUTE, both DOSUB and DOSUBL execute the code the immediately while code passed to CALL EXECUTE is executed after the DATA step completes. In this example, if CALL EXECUTE had been used, all the generated letters would have used the values of the macro variables from the last observation in our input data set since each execution of the DATA step overwrites the macro variables. Since code passed to the DOSUB/DOSUBL functions is executed immediately, the values of the macro variables in our letter resolve the values from the current observation.
A Best Practice for the DOSUBL ArgumentThe length of the code stream passed to the DOSUBL routine can not exceed 32,767 characters. For the example included above, the code was included inline to simplify reviewing the example. As a Best Practice, code to be executed should not be included inline. Instead the code can be packaged as a macro and the macro call would be the argument to the DOSUBL routine. Alternatively it could be stored in an external file that is pointed to by a fileref and that fileref would be the argument to the DOSUB routine.
This Best Practice reinforces the paradigm shift when using DOSUB/DOSUBL routines. Instead of using the Macro Language to loop and execute mutiple DATA and/or PROC steps, we can now have the DATA step do the looping and execute a macro in each loop/iteration.