1

So I've seen various pages that inform SAS Stored Process users creating stored process web pages how to do something like:

https://support.sas.com/documentation/cdl/en/stpug/62758/HTML/default/viewer.htm#p0q383asmm4bejn1i7z4q7iv5eke.htm

data _null_;
file _webout;
put '<HTML>';
put '<HEAD><TITLE>Hello World!</TITLE></HEAD>';
put '<BODY>';
put '<H1>Hello World!</H1>';
put '</BODY>';
put '</HTML>';
run;

The put HTML statements are nice and a quick way to get HTML to the page, but I'm noticing my HTML using put is getting quite messy and not maintainable.

How can I reference an external HTML file instead? I do have some SAS macros that I reference in the HTML put statements so I'm not sure if those would resolve in the external html but still interested to see a working example of referencing an external HTML file in a stored process.

UPDATE - My Example Program

In this put HTML I am just writing a form to the web page with some data populated in a drop down. I would just like to call this as raw html from an external HTML file while still resolving the SAS code embedded in the HTML like macro variable references.

%macro test;

proc sql;        
create table eqmtid_name as        
      select distinct EQMT_ID        
      from library.joined_data;        

%let neqmtid = &sqlobs;        
quit;        

data _null_;        
set eqmtid_name;        
 suffix=put(_n_,8.);        
 call symput(cats('EQMTID',suffix), EQMT_ID);        
run;    

data _null_;

file _webout;
put '<script type="text/javascript">document.body.innerHTML = "";</script>';  
put '<HTML>';  
put '<head>';  
put '<script type="text/javascript">'; 
put 'document.addEventListener("DOMContentLoaded", function initialize() {'; 
put '   var svgs = document.getElementsByTagName("svg");'; 
put '   for (i = 0; i < svgs.length; ++i) {'; 
put '    e = svgs[i];'; 
put '    e.removeAttribute("height");'; 
put '    e.removeAttribute("width");'; 
put '    e.setAttribute("width","80%");'; 
put '   }'; 
put '   '; 
put '});'; 
put '</script>'; 
put '</head>';  
put '<BODY onload="initialize()">';   
put '<HEADER class="pageheader">'; 
put '<TABLE>'; 
put '<tr>';
put '<td>'; 
put '<div class="divcenter">Header Text</div>'; 
put '</td>'; 
put '</tr>'; 
put '</TABLE>'; 
put '</HEADER>'; 
put '<FORM NAME="sub" METHOD="GET" ACTION="/SASStoredProcess/do">';            
put '<INPUT TYPE="HIDDEN" NAME="_program" SIZE="100" VALUE="/Company/IT/Development/APP/stp_program">';         
put '<INPUT TYPE="CHECKBOX" NAME="_debug" VALUE="log">Show SAS Log <br>';       
put '<TABLE>';        
put '<tr>';        
put '<td>';        
put '<label class="formitem">Equipment ID:</label>';        
put '</td>';        
put '<td>';        
put '<select class="formitem styleinput" name="EQMTID">' /        
   '<option value=""></option>' /        
   %do i = 1 %to &neqmtid; /        
   "<option value = %bquote(")%left(%trim(&&EQMTID&i))%bquote(") >&&EQMTID&i</option>" /        
   %end; /        
   '</select>';        
put '</td>';        
put '</TABLE>';        
put '<br>'; 
put '<TABLE>';  
put '<tr>'; 
put '<td>'; 
put '<INPUT class="button" class="formitem" TYPE="SUBMIT" VALUE="Search"><br>';       
put '</td>'; 
put '</FORM>'; 
put '<FORM NAME="download" TARGET="_blank" METHOD="GET" ACTION="/SASStoredProcess/do">';            
put '<INPUT TYPE="HIDDEN" NAME="_program" SIZE="100" VALUE="/Company/IT/Development/APP/export_data_stp">';         
put '<td>'; 
put '<INPUT class="button" class="formitem" TYPE="SUBMIT" VALUE="Download"><br>';       
put '</td>'; 
put '</FORM>'; 
put '</tr>'; 
put '</TABLE>'; 
put '</BODY>';             
put '</HTML>';   

run;

%mend;

%test;

UPDATE SOLVED

Thanks to the example Joe outlined below, this is what I had to code to make this work... in SAS Code:

filename htmlfile "/sasdata/IT/APP/file.html";

proc stream outfile=_webout;
begin
&streamdelim; %include htmlfile;
;;;;
run;

Note: in your html file if you have macro statements like %DO loops, you might get an error like "Error: The %DO statement is not valid in open code". In order to resolve that error I included a macro wrapper in the html file around that statement like this:

<select class="formitem styleinput" name="EQMTID">       
<option value=""></option>

%macro doeqmt;

%do i = 1 %to &neqmtid;    
"<option value = %bquote(")%left(%trim(&&EQMTID&i))%bquote(") >&&EQMTID&i</option>"
%end;

%mend;
%doeqmt;

</select>
Krusaderjake
  • 479
  • 1
  • 7
  • 19
  • 2
    Perhaps you just want to use ODS HTML or ODS HTML5 and direct the report to the _WEBOUT location? Perhaps you want to use `PROC STREAM` to process an external HTML file while replacing macro triggers? – Tom Oct 25 '17 at 18:19
  • Really need a lot more information here. What are you writing out to _webout? A PROC MEANS or something? Or just some text? Makes a huge difference to the answer. Post an example program of what you'd be putting onto the web page. – Joe Oct 25 '17 at 18:39
  • @Joe Added more detail. Tom - looks like Proc Stream might be something I can use because it looks like it does resolve the SAS code. I'll try out some trial and error with Proc Stream. – Krusaderjake Oct 25 '17 at 19:23
  • The best way to manage this is to start _from_ your web page. Check out the SASjs framework for examples: https://sasjs.io – Allan Bowe May 01 '21 at 11:00

2 Answers2

2

Depending on your exact details, there are a few ways to do this, but the simplest two are either read the HTML into a data step (in a character variable, one per line) and then putting it back out again (this is better if you need to perform some modifications on it), or as Tom suggested you can use PROC STREAM if you don't need to modify it much or if you can insert macro variables (or macros) in the raw HTML pre-file.

PROC STREAM is pretty simple. Imagine I have a hello world type file, in c:\temp\helloworld.html

<html>
  <header>
    <title>My Example Page</title>
  </header>
  <body>
    <h1> Hello, World </h1>
  </body>
</html>

Then I could write this short program:

filename htmlfile "c:\temp\helloworld.html";
filename outfile  "c:\temp\stream.html";
proc stream outfile=outfile;
begin
&streamdelim readfile htmlfile;
;;;;
run;

And I'd now have a new file, stream.html, with the same contents. And with any macro variables or macros in it resolved.

For example, let's change it just slightly:

Input:

<html>
  <header>
    <title>My Example Page</title>
  </header>
  <body>
    <h1> &mystring. </h1>
  </body>
</html>

Output, noting the new %let:

filename htmlfile "c:\temp\helloworld.html";
filename outfile  "c:\temp\stream.html";

%let mystring = Hello, World;
proc stream outfile=outfile;
begin
&streamdelim readfile htmlfile;
;;;;
run;

Note that it resolves the macro variable for us.

You can just change the outfile to _WEBOUT and you should get what you're hoping for, if I understand you right.

Joe
  • 62,789
  • 6
  • 49
  • 67
0

The way we do this in the SAS Apps team is to compile the raw HTML into SAS programs prior to deployment.

We call this approach "streaming apps" and it can work on both SAS 9 (metadata) AND Viya. Here's a breakdown: https://sasapps.io/sas-streamed-apps

Allan Bowe
  • 12,306
  • 19
  • 75
  • 124