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
MacroCore library for app developers
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

hackathon24-white-horiz.png

The 2025 SAS Hackathon Kicks Off on June 11!

Watch the live Hackathon Kickoff to get all the essential information about the SAS Hackathon—including how to join, how to participate, and expert tips for success.

YouTube LinkedIn

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
  • 1 reply
  • 657 views
  • 0 likes
  • 2 in conversation