Friday, April 13, 2012

Creating a simple UI

The point of this post is to illustrate how PROC STREAM and SAS Server Pages can be used to not only create the desired content, but also to create a user interface for a stored process (or SAS/IntrNet Application Dispatcher program). Following up on my previous posts, we need to allow the user to select which student letter is to be generated. Before describing how to do that, lets look at the results first:
We invoke the sasServerPage stored process (or SAS/IntrNet Application Dispatcher program) and just need to define the name of our input SAS Server Page which allows us to select the student for whom we'd like to generate the letter.

Here is the source for our input SAS Server Page, followed by a few notes and key points about it.

%let rc = %sysfunc(dosubl('%selectTag'));
<html>
<head>
<title>Select Letter to Generate
</head>
&streamDelim;%include srvrpgs(standardHeader.html);
<table style="width:100%; height:100%;">
<tr>
<td align="left" valign="top">
<form action="&_url" target="letter">
<input type="hidden" name="_program" value="&_program">
<input type="hidden" name="page" value="class_w_DoSub">
&selectTag
<p><input type="submit" value="Display Letter">
</form>
</td>
<td>
<iframe name="letter"
        style="width:100%; height:100%;"
        frameborder="0">
</iframe>
</td>
</tr>
</table>
</body>
</html>

Now a few notes about what is going on in the above SAS Server Page:
  • We are using DOSUBL to run some SAS code. In this case a macro (included below) that reads the SASHELP.CLASS data set and creates a macro variable that contains the text for the select tag of students that you see when you click on either of the links above to see the results.
    • The technique used here does require the M2 release of PROC STREAM/DOSUBL.
    • Note that the macro call is quoted with single quotes. Typically when functions are invoked with the %SYSFUNC macro, text is not quoted. However (again for the M2 release), for the DOSUBL function the decision was made to allow for the argument to be quoted - the rationale being that it might be desirable to allow for a single quoted string to provide a method to prevent macros froms being resolved in-line. Thus, starting with the M2 release, DOSUBL will recognize that there are leading/trailing quotes and will ignore them, thereby allowing a macro specification to be given and not expanded by %SYSFUNC.
    • Note however that the argument to DOSUBL does not need to be quoted.
    • Also note that there was no need to use a macro here. As seen in previous posts, the argument to DOSUBL could be the DATA Step code that the macro generates. I chose to use a macro here to highlight the fact that the argument to DOSUB could be a macro and also to highlight the quoting issue mentioned above.
  • The select tag is included in the output simply by using the macro variable reference &selectTag.
  • A %INCLUDE is used in the SAS Server Page to define a standard set of header text. In this example, is the the text on the grey backgound with the links to my book page on sasCommunity.org and to my web-site. I could have just as easily included trailer text, or both header and trailer text - simply by including the approapriate file.
  • Since both this user interface SAS Server Page and the SAS Server Page for the letter are self-contained (i.e., any needed SAS code is included instead of in separate programs to be run), we can simply chain these together using the same stored process, sasServerPage (which we can reference using the server created macro variable _program), and just specify the name of the input SAS Server Page using the page parameter.
  • We have complete control over how and where the output is displayed since we have complete control over what the SAS Server Pages do. In this case, we use the <iframe> tag so the user interface and the output appear in the same browser window. 
Here is the macro that we are invoking in the DOSUBL call. But before showing the code, a few disclaimers about it:
Here is the code with no explanation since it should be easy to undertand by most SAS programmers. And furthermore, it is not an approach I would want readers to think is a good idea. :-).

%macro selectTag;
 data _null_;
  length selectTag $32767;
  retain selectTag '<select name="letterObs">';
  set sashelp.class(keep=name) end=lr;
  selectTag = cats(selectTag
                  ,'<option value="'
                  ,_n_
                  ,'">'
                  ,name
                  ,'</option>'
                  );
  if lr;
  selectTag = cats(selectTag,'</select>');
  call symputx('selectTag',selectTag,'G');
 run;
%mend selectTag;