Put them back the way you found them: restoring SAS titles

Has this ever happened to you? You have a SAS program with statements that you wrote, then you make use of a macro function or %include file supplied by a helpful colleague, and when your SAS code resumes, you find that all of your SAS titles have been changed out from under you!

To be a "good citizen" within a macro function, you should return the SAS environment to the way you found it. You'll occasionally see constructs like this to store and restore SAS option values:

%let _currValidName = %sysfunc(getoption(validvarname));
%put Overriding current VALIDVARNAME setting of &_currValidName;
options validvarname=v7;

/* some statements that rely on VALIDVARNAME */

%put Restoring previous VALIDVARNAME setting to &_currValidName;
options validvarname=&_currValidName.;

(Even more is possible with PROC OPTSAVE; see Denise Poll's paper on this topic.)

But what about the titles and footnotes? Is there a way to squirrel those values away before usurping them, and then put them back the way that you found them?

Yes, there is. Even though TITLE and FOOTNOTE are global SAS statements and not system options per se, you can programmatically query the current settings from one of the SAS dictionary tables: SASHELP.VTITLE. (Despite the "VTITLE" name, this table also contains FOOTNOTE settings.)

You can use these macros (or the code within them) to save and restore the current settings for TITLE and FOOTNOTE statements:

/* Define macro to save titles */
%macro saveTitles;
data _savedTitles;
set sashelp.vtitle;
run;
%mend;

/* Define macro to restore previously saved titles */
%macro restoreTitles;
proc sql noprint;
/* Using a SAS 9.3 feature that allows open-ended macro range */
select text into :SavedTitles1- from _savedTitles where type="T";
%let SavedTitlesCount = &sqlobs.;

/* and footnotes */
select text into :SavedFootnotes1- from _savedTitles where type="F";
%let SavedFootnotesCount = &sqlobs.;

/* remove data set that stored our titles*/
drop table _savedTitles;
quit;

/* emit statements to reinstate the titles */
TITLE; /* clear interloping titles */
%do i = 1 %to &SavedTitlesCount.;
TITLE&i. "&&SavedTitles&i.";
%end;

FOOTNOTE; /* clear interloping footnotes */
%do i = 1 %to &SavedFootnotesCount.;
FOOTNOTE&i. "&&SavedFootnotes&i.";
%end;
%mend;

Sample use:

title "This is my tremendous title";
title2 "and this is a subtitle";
footnote "Created by ME";
proc means data=sashelp.class;
var weight;
run;
%saveTitles;

%someMacroThatChangesTitles();

/* restore the old titles */
%restoreTitles;
proc means data=sashelp.class;
var height;
run;

There is at least one idiosyncrasy of this approach: if your title or footnote includes a macro variable or expression, that macro will be resolved when the title is stored. So when you restore to the original value with %restoreTitles(), the value will be "stuck" as it was when you used %saveTitles(). If you dislike that limitation, then perhaps some hotshot macro programmer will add a solution here in the comments.

Learn more about SASHELP.VTITLE and DICTIONARY.TITLE from Rick Wicklin's post: How to get the current TITLE in SAS.