Published on :
Macro MIXED

Dynamic HTML Report Generation via Macros

This code is also available in: Deutsch Español Français
Awaiting validation
Attention : This code requires administrator privileges.
The script defines a main macro `message_js` which writes an HTML file by iterating over lists of macro variables. It uses utility macros (AHG prefix) to manage these lists. The script queries the `sashelp.vlibnam` view to list active libraries (excluding SASHELP, SASUSER, MAPS) and transform them into HTML links. A second macro `dosomething` checks for the existence of specific files (via a path defined in `__snapshot`) and generates the final HTML page which is then opened via a system command.
Data Analysis

Type : MIXED


Uses hardcoded data (datalines/cards4 via the AHG2arr macro) and SAS session metadata (sashelp.vlibnam).

1 Code Block
DATA STEP
Explanation :
Definition of the `message_js` macro which creates a text file (HTML) via a `_NULL_` Data Step. It iterates over the provided variable prefixes to write the content. It then executes a system command `x` to open the generated file (Windows specific 'start' command, to be adapted for Linux).
Copied!
1%macro message_js(pre,file=) ;
2
3 DATA _null_ ;
4 file "&file";
5 put "&html1";
6 put "&html2";
7 put "&html3";
8 %local i J one;
9 %DO j=1 %to %AHGcount(&pre);
10 %let one=%scan(&pre,&j,%str( ));
11 %IF not %symexist(&one._n) %THEN
12 %DO;
13 %IF %bquote(%sysfunc(rank(%substr(%bquote(&&&one),1,1))))=34
14 or %bquote(%sysfunc(rank(%substr(%bquote(&&&one),1,1))))=39 %THEN put %unquote(&&&one);
15 %ELSE put "%unquote(&&&one)";
16 %END;
17 %ELSE
18 %DO i=1 %to &&&one._n;
19 %put ############### &&&one&i;
20 %IF %bquote(%sysfunc(rank(%substr(%bquote(&&&one&i),1,1))))=34
21 or %bquote(%sysfunc(rank(%substr(%bquote(&&&one&i),1,1))))=39 %THEN put %unquote(&&&one&i);
22 %ELSE put "%unquote(&&&one&i)";
23 ;
24 put;
25 %END;
26 %END;
27 put "&html4";
28 put "&html5";
29 RUN ;
30 
31 x "start &file";
32%mend message_js ;
33option mprint;
2 Code Block
MACRO CALL Data
Explanation :
Initialization of macro variables and creation of static HTML data via calls to the utility macro `%AHG2arr` and `cards4` blocks.
Copied!
1%AHGdel(html,like=1);
2 
3%AHG2arr(html);
4cards4;
5
6
7
8
9
10;;;;
11RUN;
12 
13%AHG2arr(btn);
14cards4;
15'c:\temp\ahuige'>dd
16;;;;
17RUN;
18 
19%let alink='c:\temp\ahuige'>c;
3 Code Block
PROC SQL Data
Explanation :
Retrieval of active SAS library paths (excluding system libraries) from `sashelp.vlibnam` to construct HTML anchor tags.
Copied!
1%AHGdel(url,like=1);
2 
3PROC SQL;
4 create TABLE html as
5 select '''<a href="'||trim(path)||'">'||compress(LIBNAME)||'</a>''' as url
6 from sashelp.vlibnam
7 WHERE not LIBNAME in ( 'SASHELP','SASUSER','MAPS');
8;
9QUIT;
4 Code Block
DATA STEP
Explanation :
Transfer of the generated URLs list from the SAS table to macro variables (`url1`, `url2`, etc.) for later use.
Copied!
1DATA _null_;
2 SET html;
3 call symput('url'||%AHGputN(_n_,BEST.),TRIM(url));
4 call symput('url_N',_N_);
5RUN;
6 
7%AHGpmlike(url);
5 Code Block
MACRO CALL
Explanation :
Definition and execution of the `dosomething` macro. It checks for the presence of specific files in a `__snapshot` directory (if defined), builds dynamic links if the files exist, and finally calls `message_js` to generate the HTML report.
Copied!
1%macro dosomething(arr);
2%AHGdel(&arr,like=1);
3%local i j all;
4%IF %symexist(__snapshot) %THEN
5%DO;
6 %let all= programs_stat replica_programs ;
7 %let j=0;
8 %DO i=1 %to %AHGcount(&all);
9 %PUT GREAT &I;
10 %IF %sysfunc(fileexist(&__snapshot\%scan(&all,&i,%str( )))) %THEN
11 %DO;
12 %AHGincr(j);
13 %let &arr&j=%bquote('<a href="&__snapshot\%scan(&all,&i,%str( ))">%scan(&all,&i,%str( ))</a>');
14 %AHGpm(&arr&j);
15 %LET &ARR._N=&j;
16 %END;
17 %END;
18
19%END;
20 
21%message_js(URL btn alink %IF %symexist(__snapshot) %THEN &arr;,file=%AHGtempdir\js.html);
22/*&arr*/
23%mend;
24%doSomething(APATH33);
This material is provided "as is" by We Are Cas. There are no warranties, expressed or implied, as to merchantability or fitness for a particular purpose regarding the materials or code contained herein. We Are Cas is not responsible for errors in this material as it now exists or will exist, nor does We Are Cas provide technical support for it.
Banner
Expert Advice
Expert
Stéphanie
Spécialiste Machine Learning et IA.
« This script demonstrates a sophisticated technique for transforming SAS into a dynamic content engine. By combining metadata introspection with low-level file writing, it creates an automated "Launchpad"—an interactive HTML interface that maps the server’s active libraries and physical file structures in real-time.

Technical Pillars of this Solution:
Dynamic Metadata Introspection: The script queries sashelp.vlibnam to audit the current session's environment. By extracting physical paths and logical names, it builds a real-time directory of the server’s infrastructure, excluding system libraries to maintain a clean, user-focused interface.

DATA NULL as a Web Renderer: The message_js macro utilizes the FILE and PUT statements to write raw HTML code line-by-line. A key technical highlight is the use of %SYSFUNC(RANK(...)) to check ASCII values (34 for double quotes, 39 for single quotes). This ensures that macro variables are injected into the HTML/JavaScript context with correct quoting, preventing syntax errors in the browser.

Array-Style Macro Mapping: Through utility macros like %AHG2arr, the script converts static text blocks (from cards4) and SQL results into pseudo-arrays of macro variables (e.g., url1, url2, ..., url_N). This allows the renderer to loop through an unknown number of items dynamically without hardcoding.

Infrastructure Validation: The dosomething macro introduces operational intelligence by using fileexist(). It doesn't just list potential links; it verifies the physical presence of files within the __snapshot path. Only verified assets are rendered as hyperlinks, ensuring a "broken-link-free" reporting experience. »