I thank Tom, Ksharp, and Dr. Rick for their helpful insights and comments.
I have made progress in my attempt to control ODS PDF processing from within an IML module, but I'm not 100% done yet.
I adopted many of the suggestions proffered and include the revised ODS_PDF() module below:
options ls=200 ps=9999 ;
libname FUZZYLIB 'C:\Users\RossMaster\Documents\My SAS Files\Fuzzy_Logic_Toolbox_SAS' ;
proc iml ;
reset storage=fuzzylib.fuzzylib ;
/*load module=_all_ ;*/
/*remove module=( ods_pdf ) ;*/
show storage ;
start ods_pdf( pdf_file=, verbose=0 ) ;
/* purpose: manage ODS environment to capture PDF output into an external file
*
* pdf_file ::= character string containing name of PDF file to be created in
* directory indicated by SAS_EXECFILEPATH macro variable
*
* if parameter value is empty, the ODS PDF CLOSE command will be issued
*
* verbose ::= flag to control display of intermediate results of each test and action performed
*
* example:
* proc iml ;
* reset storage=mylib ;
* load module=_all_ ;
*
* run ods_pdf( 'cholesterol_histogram', 1 ) ; *** run in verbose mode ***
*
* submit ;
* title 'Distribution of Cholesterol' ;
* proc sgplot data=sashelp.heart ;
* histogram cholesterol ;
* run ;
* title ;
* endsubmit ;
*
* run ods_pdf() ;
* quit ;
*/
if ^isEmpty( pdf_file )
then do ;
/* create path to external file */
ext_file = cats(
substr( "%sysget( SAS_EXECFILEPATH )"
, 1
, length( "%sysget( SAS_EXECFILEPATH )" ) - length( "%sysget( SAS_EXECFILENAME )" )
)
, pdf_file
, '.pdf'
) ;
ext_file = quote( ext_file ) ; /* surround external file with double quotes */
if verbose then print ( cat( 'External PDF output file: ', ext_file )) ;
/* use filename fcn to assign file reference to external PDF output file
/* check precedence of file reference PDF_REF using global fcn fileref
* and existence of ext_file.pdf using global fcn fexist
*
* fileref return codes:
* < 0 fileref is assigned but file does not exist
* 0 fileref is assigned and file exists
* > 0 fileref is not assigned and file does not exist
*/
rc = filename( 'PDF_REF', ext_file ) ;
if verbose then print ( cat( "1. rc = filename( 'PDF_REF', ext_file ) : rc=", rc, choose( rc = 0, ' successful', ' unsuccessful' ))) ;
fileref_flg = fileref( 'PDF_REF' ) ; /* get status of PDF_REF link to external file */
if verbose then print ( catt( "2. fileref_flg = fileref( 'PDF_REF' ) : fileref_flg=", fileref_flg )) ;
if fileref_flg < 0
then do ;
rc = filename( 'PDF_REF', '' ) ; /* clear file reference */
if verbose then print ( catt( "3. fileref_flg > 0. rc = filename( 'PDF_REF', '' ) : rc=", rc, choose( rc = 0, ' successful', ' unsuccessful' ))) ;
end ;
else
if fileref_flg = 0
then do ;
/* if fileref points to existing file, delete file and release file reference*/
if fileexist( ext_file )
then do ;
rc = fdelete( 'PDF_REF' ) ;
if verbose then print ( catt( "4. fileref_flg = 0. rc = fdelete( 'PDF_REF' ) ; rc=", rc, choose( rc = 0, ' successful', ' unsuccessful' ))) ;
rc = filename( 'PDF_REF', '' ) ;
if verbose then print ( catt( "5. fileref_flg = 0. rc = filename( 'PDF_REF', '' ) : rc=", rc, choose( rc = 0, ' successful', ' unsuccessful' ))) ;
end ;
end ;
else
if fileref_flg > 0
then do ;
if verbose then print ( catt( "6. fileref_flg > 0. Fileref is not assigned and external file" )) ;
end ;
/******************************************************************************/
/* have prepared ODS environment
/* link file reference to external file
/* establish ODS PDF environment
/******************************************************************************/
stmt = catt( "rc = filename( 'PDF_REF', ", ext_file, ") ;" ) ;
call execute( stmt ) ; /* establish fresh fileref-PDF output file linkage */
if verbose then print ( catt( "7. rc = filename( 'PDF_REF', 'ext_file' ): rc=", rc, choose( rc = 0, ' successful', ' unsuccessful' ))) ;
/* link fileref PDF_REF to external file to capture ods pdf output */
call execute( 'ods listing close ;' ) ;
call execute( 'ods pdf file=', ext_file, ' ;' ) ;
end ;
else do ;
/* close external file linked to PDF_REF */
call execute( 'ods pdf close ;' ) ;
call execute( 'ods listing ;' ) ;
rc = filename( 'PDF_REF', '' ) ; /* clear file reference */
if verbose then print ( catt( "8. rc = filename( 'PDF_REF', '' ) : rc=", rc, choose( rc = 0, ' successful', ' unsuccessful' ))) ;
end ;
finish ods_pdf ;
/* store latest version of ods_pdf() */
store module=ods_pdf ;
show storage ;
/******************************************************************************/
/* test code
/******************************************************************************/
run ods_pdf( 'Cholesterol', 1 ) ;
submit ;
title 'Distribution of Cholesterol' ;
proc sgplot data=sashelp.heart ;
histogram cholesterol ;
run ;
title ;
endsubmit ;
run ods_pdf( , 1 ) ;
/***************************************************************************/
run ods_pdf( 'height' ) ;
submit ;
title 'Histogram of Class Height' ;
proc sgplot data=sashelp.class ;
histogram height ;
run ;
title ;
endsubmit ;
run ods_pdf( , 1 ) ;
quit ;
The module compiles error-free and produces the first plot, "Distribution of Cholesterol", correctly. Then I invoke the ODS_PDF() module again and incur a system error (vide ods_pdf.txt). So maybe I have been a bad boy. I changed the ODS LISTING CLOSE to ODS EXCLUDE ALL as Dr. Rick suggests (vide ods_pdf_test_1.sas) and saw that ODS EXCLUDE ALL + ODS PDF File=<PDF output filename> suppresses the PDF output (vide ods_pdf_test_1.txt) but ODS LISTING CLOSE + ODS PDF File=<PDF output filename> works properly. And if I use ODS LISTING CLOSE on both SGPLOT calls, I see two histograms, as was to be expected.
Hence, I am still doing something wrong and my neuron is overloaded so I am asking for Community assistance. I see that if I use ODS LISTING control over ODS output, I strike out when I try to produce multiple graphics sequentially, so maybe I have not set up the appropriate ODS PDF environment. When I use ODS EXCLUDE, I turn off PDF output despite using the ODS PDF File= statement after ODS EXCLUDE ALL. I am confused.
Ross
... View more