BookmarkSubscribeRSS Feed
☑ This topic is solved. Need further help from the community? Please sign in and ask a new question.
Babloo
Rhodochrosite | Level 12

@AhmedAl_Attar Still I get the same error when I tried to use Filename statement per your instruction. I kept the following line before proc steam.

 

Filename sample '/home/babloo/test/_webout';

Even I tried this without any path,

 

Filename sample '_webout';

Am I missing something?

AhmedAl_Attar
Ammonite | Level 13

@Babloo 

Typical SAS Filename Statement is composed as follows

FILENAME <FileReference> <Location | TEMP>;

Try this

Filename _webout TEMP; /* Will place the file in the same location as your SAS WORK library */
/* or */
Filename _webout '~/mywebout.html'; /* Explicitly specifying physical output file name */

Hope this helps

Babloo
Rhodochrosite | Level 12

@AhmedAl_Attar  thanks but still the other error persists. ERROR 180-322: Statement is not valid or it is used out of proper order.

 

Log:

 

81   Filename _webout TEMP;
82   
83   proc stream outfile=_webout quoting=both;
84   BEGIN
85   <html>
86   <body><title>Select Products</title><body>
87   %let rc =%sysfunc(dosubl(
88   proc sql noprint;
89   Figure 8. First Attempt to Include SAS Code in a SAS Server Page
90   11
91   select distinct
92    '<input type="checkbox" name="product" value="'
93    ||strip(product)
94    ||'">'
ERROR 180-322: Statement is not valid or it is used out of proper order.
NOTE: PROC SQL set option NOEXEC and will continue to check the syntax of statements.
AhmedAl_Attar
Ammonite | Level 13

@Babloo 

I think when you copied the code lines from the paper, some additional non SAS lines where included!

Figure 8. First Attempt to Include SAS Code in a SAS Server Page
11

I ran this code without any issues and generated the desired result.

Filename _webout TEMP;

%let rc = %sysfunc(dosubl(
SAS Code - potentially spanning multiple lines
));
proc stream outfile=_webout quoting=both;
BEGIN
<html>
<body><title>Select Products</title><body>
%let rc =%sysfunc(dosubl(
proc sql noprint;
select distinct
 '<input type="checkbox" name="product" value="'
 ||strip(product)
 ||'">'
 ||strip(product)
into:checkboxes separated by '<br>' 
from sashelp.shoes;
quit;
)); /* End both the DOSUBL function call and the 
%SYSFUNC macro function */
&checkboxes
</body>
</html>
;;;;
run;
<!DOCTYPE html>
<html>
<head>
<meta name="generator" content=
"HTML Tidy for HTML5 for Windows version 5.0.0.RC1">
<title>Select Products</title>
</head>
<body>
<form><input type="checkbox" name="product" value="Boot">Boot<br>
<input type="checkbox" name="product" value="Men's Casual">Men's
Casual<br>
<input type="checkbox" name="product" value="Men's Dress">Men's
Dress<br>
<input type="checkbox" name="product" value="Sandal">Sandal<br>
<input type="checkbox" name="product" value="Slipper">Slipper<br>
<input type="checkbox" name="product" value="Sport Shoe">Sport
Shoe<br>
<input type="checkbox" name="product" value=
"Women's Casual">Women's Casual<br>
<input type="checkbox" name="product" value=
"Women's Dress">Women's Dress</form>
</body>
</html>

Boot
Men's Casual
Men's Dress
Sandal
Slipper
Sport Shoe
Women's Casual
Women's Dress

 

 

Babloo
Rhodochrosite | Level 12

@AhmedAl_Attar How did you got the HTML code which you showed in your post? I executed the SAS code in SAS Studio based on your instructions and there is no error in the log now. However I could not see the result. May I know where to check the result?

AhmedAl_Attar
Ammonite | Level 13

@Babloo 

When you use the 'TEMP' keyword for in your Filename statement, SAS creates a special physical file under the WORK Library path called something like (#LN000XX) XX is a number.

You can use this statement to find your current WORK Library physical path

%put %sysfunc(pathname(WORK));

You'll need to look there or a level above it for the #LN000XX file 😉Once you open it (#LN000XX) using a Browser, you should be able to see the Check Boxes.

 

PS. I used UltraEdit to reformat/tidy the generated HTML as well as Apply "Browser View" to show the Check Boxes.  

Babloo
Rhodochrosite | Level 12
For me WORK path is /sastmp/... I don't know how to go to this path. I
will check with SAS admin on this.

In the same location we can see the generated HTML which you shown in your
post? If not, where to see it?

I know I'm asking many questions and I'm sorry for that.
Tom
Super User Tom
Super User

@Babloo wrote:
For me WORK path is /sastmp/... I don't know how to go to this path. I
will check with SAS admin on this.

In the same location we can see the generated HTML which you shown in your
post? If not, where to see it?

I know I'm asking many questions and I'm sorry for that.

If you are using SAS/Studio to test the HTML generation then you can use one of its features to let you DOWNLOAD the file as soon as it is generated.  Basically write the file using the fileref _DATAOUT.  And then also set the macro variables _dataout_name and _dataout_mime_type

 

I am still not sure if you need to use the fancy Viya features for web interfacing.  You mentioned that the page is STATIC, but it needs information from a SAS dataset to generate the selection lists.  If the page is truly static and the information in the SAS dataset is reasonably stable then you can still get away with just making a SAS program that writes the HTML file.  You will just need to re-generate the HTML every time you make changes to the SAS dataset.

AhmedAl_Attar
Ammonite | Level 13

@Babloo 

Typically the WORK Library physical path would look something like this

/<SomePath>/SAS_workxxxxxxxxxxxx_<Fully Quqlified Server Name>/

In both SAS Studio 5.2 / SAS StudioV your SAS Viya Admin may have only allowed/configured certain folders that can be exposed via the Explore Navigation pane.

 

Therefore I would contact your SAS Viya Admin and request he/she download that file for you. To make this process more clear, try to assign the File reference as follows

FILENAME _WEBOUT "%sysfunc(pathname(WORK))/_webout.html";

 This way you'll have a physical file name he/she can look for under the /sastmp/ folder

 

Hope this helps

 

Babloo
Rhodochrosite | Level 12

@AhmedAl_Attar  I added this line Filename _webout "/ifrs/test/_webout.html"; on yesterday and it was working fine and I could see the html file in the mentioned location. When I executed the same code today, it ended up with error as shown below. Even I removed the HTML file from the location where it was created on yesterday and even I changed the path in Filename statement as well but still the same error. Any help?

 

Filename _webout "/ifrs/test/_webout.html";
ERROR: At least one file associated with fileref _WEBOUT is still in use.
ERROR: Error in the FILENAME statement.
AhmedAl_Attar
Ammonite | Level 13

@Babloo 

Where you running this code?

  • From regular/standard SAS Studio Program entry? --> This shouldn't cause an issue
  • From within a Job Definition Program entry? --> The _webout file reference would be already defined and you should not change it!

 

If the regular SAS Studio program entry causing the issue, this could mean your yesterday's SAS process ID/Session never terminated properly!?

You can

  • ssh to your SAS Compute Server, via the Windows CMD window, or any other Remote Terminal program and run the following Linux Command

$ ps -ef | grep <PutYourUserIDHere>

Note: The above Linux command should show you what Linux Processes you have running under your Network ID, look for anything from last night and try to kill it using the following command

$ kill -9 <PID> 

 

  • Ask your SAS or Linux Administrator to kill your lingering processes from last night. Your SAS Admin may not able to, but your Linux Admin should be able without any issues.
  • Try different filename altogether if possible

Hope this helps

Kurt_Bremser
Super User

The way I see it, the library you reference in

data-library=

has to be defined and assigned in SAS already, either through metadata or in the autoexec file(s).

Babloo
Rhodochrosite | Level 12

@AhmedAl_Attar I came across the following articles today and I observed that we can use a rest API call to retrieve the distinct values of a column. from a SAS dataset. 'Proc http' does this it seems. I can try this later.

 

Creating JES Prompts and Output Using the Viya Reports API - SAS Support Communities

Executing a JES Job Using JavaScript - SAS Support Communities

 

Now my question is how to embed (or add) the HTML code which I already wrote with the Proc http which I'm going to write?

AhmedAl_Attar
Ammonite | Level 13

Hi @Babloo,

Few of points to keep in mind, when you analyze what's this article "Creating JES Prompts and Output Using the Viya Reports API" is doing

  1. Proc HTTP is executed by SAS to retrieve data in JSON format from the Viya Reports API
  2. The Drop Down Prompt "The prompt below contains the 10 most recently created VA reports." is constructed using JavaScript, which can found here , and not SAS or Proc HTTP!

 

// make request to reports API
var xmlhttp = new XMLHttpRequest();
var url = "/reports/reports?limit=10&sortBy=creationTimeStamp:descending";
xmlhttp.onreadystatechange = function() {
    if (this.readyState == 4 && this.status == 200) {
        var myArr = JSON.parse(this.responseText);
        createSelection(myArr);
    }
    else {
    	document.getElementById("reportList").innerHTML = "Status: " + this.status;
	}
}
// convert response into a dropdown
function createSelection(rList) {
    var prompt = '<select name="reportSelect">';
    var i;
    for(i = 0; i < rList['items'].length; i++) {
        prompt += '<OPTION VALUE="' + rList['items'][i].id + '">' +
        rList['items'][i].name;
    }
    prompt += '</select>'
    document.getElementById("reportList").innerHTML = prompt;
}

This means, you'll need to have an equivalent SAS Program/JES Job on the server, similar to the Viya Report API, that you can pass it a Data Set name, and Column name, and it returns JSON response, so your JavaScript function could transform it into a HTML <select> <option> </select> Tags

 

 

I would guess the steps for that would be

1. Create new Viya Job that takes two parameters (dsName, ColName), and it returns JSON

2. Create new Viya Job that follows the steps in this article "Creating JES Prompts and Output Using the Viya Reports API", where it's using AJAX (xmlhttp = new XMLHttpRequest();), and calls your job that you created in Step 1 via  (var url = "/<jobLocation>/<JobName>?dsName=sashelp.cars&colName=models";)

3. You create custom JavaScript Function similar to   "function createSelection(rList)" but it may take three parameters instead of 1 (rList, ElementId,SelName)

  • rList: Json Array of list elements/Options
  • ElementID: used for  document.getElementById("<ElementID>").innerHTML  <-- You'll need to verify JavaScript Syntax for the substitution 
  • SelName: used for var prompt = '<select name="<SelName>">'  <-- You'll need to verify JavaScript Syntax for the substitution 

Hope this helps

AhmedAl_Attar
Ammonite | Level 13

Hi @Babloo 

Here is how I was able to get this running in our Viya 3.5 now 😊

  • Created a new Job Definition called 'getDsColValues' with 'No embedded form', that accepts two custom parameters (s_dsName, s_colName) and returns a unique list of values in JSON format.

The Job was saved under the Public Folder (/Public/getDsColValues). Here is it's SAS code.

 

/* Generate unique list of values */
Proc summary data=&s_dsName NWAY missing;
	class &s_colName;
	output out=work._unique(drop=_type_);
run;
proc json out=_webout pretty nosastags;
	export work._unique;
run;

 

 

 

<html>
   <head>
      <link rel="stylesheet" href="/SASJobExecution/theme">
   </head>
   <body>
      <h1 class="jobexec_sample_name">Creating JES Prompts and Output Using SAS Data sets</h1>
      <p>
         The prompts below contains items pulled dynamically from SAS data sets. 
         <br><br>
         To view data set records, make a seletion and press 'submit'
      </p>
      <p>
      <form action="javascript&colon;submitForm();">
         <!-- Define Dropdown/Select place holders -->
         <div id="yearList"></div>
         </nbsp>
         <div id="stateList"></div>
         </nbsp>
         </nbsp>
         <p></p>
         <input type="submit">
      </form>
      <center>
         <div id="JobResults"></div>
      </center>
   </body>
   <script>
		
		// CREATE AN XMLHttpRequest OBJECT, WITH POST METHOD.
		var formData = new FormData();
		// This is my SAS Job that returns JSON Objects Array of unique values list from a SAS Data set.
		formData.append("_program", "/Public/getDsColValues");  
		formData.append("_action", "execute");
		formData.append('_csrf', "$CSRF$");
		formData.append('s_dsName', "sashelp.prdsal2"); // SAS Data set specified for the s_dsName parameter
		formData.append('s_colName', "year"); // Year column specified for the s_colName parameter
		formData.append("_output_type", "json");

        // Declare Ajax request object for the YearList
        var xhr = new XMLHttpRequest();
		xhr.addEventListener("error", function (event) {
			alert("Something went wrong.");
		});
        xhr.onreadystatechange = function () {
			if (this.readyState == 4) {
				if (this.status == 200) {
					// Pass Parsed JSON DATA, and other info to the custom function
					createSelection(JSON.parse(this.responseText),'year','YEAR',1);
				}
	            else {
			    	document.getElementById("yearList").innerHTML = "Status: " + this.status;
				}
			}
        };

		// Declare Ajax request object for the StateList
        var xhr2 = new XMLHttpRequest(); 
		xhr2.addEventListener("error", function (event) {
			alert("Something went wrong.");
		});
        xhr2.onreadystatechange = function () {
			if (this.readyState == 4) {
				if (this.status == 200) {
					// Pass Parsed JSON DATA, and other info
					createSelection(JSON.parse(this.responseText),'state','STATE',5);
	            }
			    else {
			    	document.getElementById("stateList").innerHTML = "Status: " + this.status;
				}
			}

        };
		
        // Submit the request and get Year data elements from SAS data set
		xhr.open("post", "/SASJobExecution/");
		xhr.send(formData);

		// Submit the request and get State data elements from SAS data set
		xhr2.open("post", "/SASJobExecution/");
		formData.set('s_colName', "state"); // Reuse the same formData object, but just change the value of the s_colName parameter
		xhr2.send(formData);

		// Display a temporary message in the DIV
		document.getElementById("yearList").innerHTML = "Please wait ... ";
		document.getElementById("stateList").innerHTML = "Please wait ... ";

		//Declare a Function to convert JSON response into a Dropdown selection widget
		function createSelection(rList,prefix,name,size = 1) {
		  var listName = prefix + 'List';
		  var prompt = '<select name="' + prefix + 'Select" size="' + size + '">';
		  var i;
		  //alert(JSON.stringify(rList));

		  for(i = 0; i < rList.length; i++) {
			  prompt += '<OPTION VALUE="' + rList[i][name] + '">' + rList[i][name] + ' :' + rList[i]._FREQ_ + '</option>';
		  }
		  prompt += '</select>'
		  document.getElementById(listName).innerHTML = prompt;
		}

		function submitForm() {
			var formData = new FormData();
			formData.append("yearParm", document.querySelector('[name="yearSelect"]').value);
			formData.append("stateParm", document.querySelector('[name="stateSelect"]').value);
			formData.append("_program", "$PROGRAM$");
			formData.append("_action", "execute");
			formData.append('_csrf', "$CSRF$");

			var request = new XMLHttpRequest();
			request.addEventListener("error", function (event) {
				alert("Something went wrong.");
			});
			request.onreadystatechange = function () {
				if (this.readyState == 4) {
					if (this.status == 200) {
						document.getElementById("JobResults").innerHTML = this.responseText;
					}
					else {
						document.getElementById("JobResults").innerHTML = "Status: " + this.status;
					}
				}
			};
			request.open("post", "/SASJobExecution/");
			request.send(formData);
		  
			// Display a temporary message in the DIV
			document.getElementById("JobResults").innerHTML = "Please wait ... ";
		}
   </script>
</html>

 

I stopped here once I was able to populate my HTML Select/DropDown widgets from SAS, after all, this is just Prove of Concept 😉

 

I hope this gets your closer to your goal.

But I'll just repeat my advice again, for SAS Viya 3.5 stick with the TASK Prompts, out of the box, they are probably a lot more feature rich compared to what you would spend time to build using JavaScript/HTML/CSS combination.

 

Good luck,

Ahmed

hackathon24-white-horiz.png

2025 SAS Hackathon: There is still time!

Good news: We've extended SAS Hackathon registration until Sept. 12, so you still have time to be part of our biggest event yet – our five-year anniversary!

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.

SAS Training: Just a Click Away

 Ready to level-up your skills? Choose your own adventure.

Browse our catalog!

Discussion stats
  • 66 replies
  • 5356 views
  • 32 likes
  • 5 in conversation