BookmarkSubscribeRSS Feed
jamesBFD
Obsidian | Level 7

I'm creating a Stored Process that iterates multiple times through a data set and shows different subsets of it via Proc Print. I'd like to have those Proc Prints be able to expanded and hidden. (They could be quite large and the users won't want to scroll through them all the time.) I've got HTML code that does the hiding/expanding but including it via file _webout in my Stored Process is resulting in the "maximum level of nesting of macro functions exceeded" error. 

 

So my method for displaying a mixture of HTML and SAS ODS results has a hard cap of 10 HTML blocks. I'm therefore wondering if there is a better way of doing this?

 

Below is SAS code of what I'm trying to do using the SASHELP Baseball library (as I can't put my actual code on here):

 

data _null_;
  file _webout;
  put '  <HTML>';
  put '  <HEAD><TITLE>Expandable Blocks Test 1</TITLE></HEAD>';
  put '  <BODY><H1>Expandable Blocks Test 1</H1>';
  put '  <p>Beginning of test</P>';	
  put '  </BODY></HTML>';
  put '	<style>';
  put ' .accordion { background-color: #eee; color: #444; cursor: pointer; padding: 18px; width: 100%; border: none; text-align: center; outline: none; font-size: 18px; transition: 0.4s; }';
  put ' .active, .accordion:hover { background-color: #ccc; }';
  put ' .panel { padding: 0 18px; display: none; background-color: white; overflow: hidden;}';
  put '	</style>';
run;
 
%macro ListPlayers(team);

    Title1 "<H1>This <i>is </i> &team !</H1>"; 

%STPEND; 
data _null_;
  file _webout;
  put '<button class="accordion">Team List</button><div class="panel">';
run;
%STPBEGIN;

	 proc print data=sashelp.Baseball;
        where team="&team";
    run;

%STPEND; 
data _null_;
  file _webout;
  put '</div>';
run;
%STPBEGIN;

%mend;


%macro LoopTeams;

    proc sql;
        Select  distinct(Team)
        into    :TeamName1-
        From    sashelp.baseball
        Order by Team Asc;
    quit;

    %local i;

    %do i=1 %to &sqlobs;
        %ListPlayers(&&TeamName&i);
    %end;

%mend;

%STPBEGIN;

%LoopTeams;

%STPEND; 

;*';*";*/;quit; 

data _null_;
  file _webout;
  put'	<script>';
  put'	var acc = document.getElementsByClassName("accordion");';
  put'	var i;';
  put'	for (i = 0; i < acc.length; i++) {';
  put'	  acc[i].addEventListener("click", function() {';
  put'		this.classList.toggle("active");';
  put'		var panel = this.nextElementSibling;';
  put'		if (panel.style.display === "block") {';
  put'		  panel.style.display = "none";';
  put'		} else {';
  put'		  panel.style.display = "block";';
  put'		}';
  put'	  });';
  put'	}';
  put'	</script>';
run;

If anyone can help that would be great. Thanks.

1 REPLY 1
AllanBowe
Barite | Level 11

Yes indeed - the 'better way' would be to seperate style and content (frontend and backend) by putting your HTML / Javascript directly on the SAS Web Server (eg htdocs) and calling SAS Stored Processes via AJAX to retrieve just the data you need, when you need it.

 

This approach is outlined here:  https://www.rawsas.com/building-web-apps-with-sas/

/Allan
SAS Challenges - SASensei
MacroCore library for app developers
SAS networking events (BeLux, Germany, UK&I)

Data Workflows, Data Contracts, Data Lineage, Drag & drop excel EUCs to SAS 9 & Viya - Data Controller
DevOps and AppDev on SAS 9 / Viya / Base SAS - SASjs

Ready to join fellow brilliant minds for the SAS Hackathon?

Build your skills. Make connections. Enjoy creative freedom. Maybe change the world. Registration is now open through August 30th. Visit the SAS Hackathon homepage.

Register today!
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
  • 1 reply
  • 422 views
  • 0 likes
  • 2 in conversation