BookmarkSubscribeRSS Feed
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>';
%macro ListPlayers(team);

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

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

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

data _null_;
  file _webout;
  put '</div>';


%macro LoopTeams;

    proc sql;
        Select  distinct(Team)
        into    :TeamName1-
        Order by Team Asc;

    %local i;

    %do i=1 %to &sqlobs;






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 ( === "block") {';
  put' = "none";';
  put'		} else {';
  put' = "block";';
  put'		}';
  put'	  });';
  put'	}';
  put'	</script>';

If anyone can help that would be great. Thanks.

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:

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



Registration is open! SAS is returning to Vegas for an AI and analytics experience like no other! Whether you're an executive, manager, end user or SAS partner, SAS Innovate is designed for everyone on your team. Register for just $495 by 12/31/2023.

If you are interested in speaking, there is still time to submit a session idea. More details are posted on the website. 

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.

Get the $99 certification deal.jpg



Back in the Classroom!

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

View all other training opportunities.

Discussion stats
  • 1 reply
  • 2 in conversation