BookmarkSubscribeRSS Feed
Obsidian | Level 7

My SAS is weak and my javascript is remedial at best


I would like to:

1) From a javascript function found in a Macro of a Stored Procedure

 a) pass variables to a global variable

 b) run a macro found in the same stored procedure

 c) populate variable values from the Macro back into the javascript function that called the Macro


I hope to not use HTML submit to perform data interaction

** my obs are many and each obs have over 12 culumns


    Once the concept is prooven I hope to use the same method to append and update the sas data set. 


Below is a snippet what I've been working on that is incomplete in many ways


%global  provs mrncnt mrns;


%macro prepdata;


%let mrn =
(proc sql
Select MRN from data_src
where prov_name =&prov



%let mrncnt=
(proc sql
Select count(mrn) from data_src
where prov_name =&prov

%mend prepdata;


%Macro openfrm;
data _null_;
file _webout;

thissrv = symget('_url');
thispgm = symget('_program');


put '<!DOCTYPE html>';
put '<HTML>';
put '<head>';
put '<style>';


put "th, td, input {";
put "text-align: center;";
put "text-wrap:unrestricted;";
put "}";


put "BORDER:hidden;";
put "background-color:#FFFFFF;";
put "color:#000000;";
put "}"


put '</style>';


put '<script type="text/javascript" language="JavaScript">';

put 'function pasvar(){';
put 'var aprov =document.getElementById("Prov")';
put 'var ' &provs ' = aprov.options[aprov.selectedIndex].text';
???  call the macro prepdata ????
put "openadd('1st',"
put "}";


put 'var nm=0;';


put 'function openadd(a,b){';
PUT "if(nm<0){nm=0}for( i=1; i<1+b; i++){nm = i;add(a,i);}";
PUT "}";


put "function add(el,rw){";


put "targEl=document.getElementById(el);";
Put 'tbody = targEl.getElementsByTagName("tbody")[0];';

put 'row = document.createElement("TR");';

put 'cell1 = document.createElement("TD");';
put 'inp1 = document.createElement("INPUT");';
put 'inp1.setAttribute( "type","text");';
put 'inp1.setAttribute( "name","line");';
put 'inp1.setAttribute( "id","line_" +nm);';
put 'inp1.setAttribute( "value", nm);';
put 'inp1.setAttribute( "size","3");';
put 'inp1.setAttribute( "disabled",true);';
put 'inp1.setAttribute( "style","border:none");';
put "cell1.appendChild(inp3);";

put "row.appendChild(cell3);";
put "tbody.appendChild(row);";

put "}";


put '</SCRIPT>';


put '</HEAD>';

put '<BODY>';


 '  thissrv +(-1) '" method=post>';
put '<input type="hidden" name="_program" value="
 ' thispgm +(-1) '">';


put '<INPUT TYPE="HIDDEN" NAME="reqtype" VALUE="add">';
put '<table bgcolor="#3399FF">';
put '<tr>';
put '<th>';
put '<table align="LEFT" border="0" cellspacing="0" bgcolor="#FFFFFF" >';
put '<tr>';
put '<th>Provider:</th>';
put '</tr>';

put '</tr>';

put '</table>';

put '</th>';

put '</tr>';

put '</table>';

put '<table id= "1st" border="0" cellspacing="0" bgcolor="#FFFFFF" >';

put '<tbody>';

put '<tr name = "row1" >';

put '<TD><input type="text" name="line_i" id="line_i" size="3" value ="#" READONLY="READONLY" tabindex="-1"></TD>';

put '</tr>';


put '</tbody>';

put '</table>';

put '</table>';
put '</body>';

put '</html>';

%mend openfrm;


Thak you in advance




Super User

When you call a stored process via the SASStoredProcess URL, the macro variables defined as stored process parameters are included in the URL. Passing complete SAS steps will probably scramble your URLs, and executing code from the URL will be a severe security risk.

Instead I would define one simple parameter which then is used in the stored process to decide which branch to follow. 


<empty> display empty form

1 search for records

2 add records

3 delete records

and so on

Keep your stored process parameters as simple as possible, so your URLs stay human-readable and don't cause errors or security problems (by displaying sensitive data or allowing code injection)

Obsidian | Level 7

I agree.  That is why I want to keep the entire SP together in one program. 


If possible, it seems best to call macros from within the stored process via javascript funtions and also use javascript functions to pass variables between the macros.


This should keep all data out of the URL.

Lapis Lazuli | Level 10

Hi Tim,


Please don't take this the wrong way, but there are a few really bad practices with what you're trying to do here, from both a SAS and web application programming perspective. 


In any case, here are my 2 cents:


1) If you absolutely have to use SAS to serve your static HTML/JS content, you're better off storing your .html code in a static file and outputting it from your macro like this:

  data _null_;
    infile myStaticCodeStoredSomewhere.html;
    file _webout;
    put _infile_;

This will work fine as you have no variables in your html, and it will make it considerably easier to edit. 


2) If you use HTTP POST to submit your data you will be able to pass your code in as part of the body of the request and no variables will be visible in the URL, if that's what you're concerned about. Unless your deployment is properly secured with TLS then this is just security through obscurity. 


What exactly are you trying to do here, what's the bigger picture? Build some kind of cascaded filter? Edit rows of data?


What version of SAS are you running? What's your level of Javascript experience? Is this Javascript your own code? 






Obsidian | Level 7

About the setup:

There is no access to a  web server only the SAS 9.4 Stored Process web portal.  This seems powerful and secure enough for our purpose.



We are working to bring data into a form based on filterd values.  Interact with it (edit fields) Add additional observation lines.

Then submit the data back into the host table updating the edited fields and appending the additional lines of observations.


Code: I've typed up the code and the supporting concepts are learned recently



Looking at excepts of “SAS Server Pages: Generating Dynamic Content”  from Don Henderson (who I had the pleasure of meeting), it's uncertain that calling a Macro and passing variables from Javascript without using submit can be accomplished.








The early bird rate has been extended! Register by March 18 for just $695 - $100 off the standard rate.


Check out the agenda and get ready for a jam-packed event featuring workshops, super demos, breakout sessions, roundtables, inspiring keynotes and incredible networking events. 


Register now!

How to Concatenate Values

Learn how use the CAT functions in SAS to join values from multiple variables into a single value.

Find more tutorials on the SAS Users YouTube channel.

Click image to register for webinarClick image to register for webinar

Classroom Training Available!

Select SAS Training centers are offering in-person courses. View upcoming courses for:

View all other training opportunities.

Discussion stats
  • 4 replies
  • 3 in conversation