/*---------------------------------------------------------*/ %macro grtitle( /* Modify graph templates to enable title overrides. This */ /* macro searches the part of the template search path */ /* that does not include work.templat. It puts the */ /* modified templates in work.templat. */ /*---------------------------------------------------------*/ path=, /* ODS template path. Leave blank to modify all graph */ /* templates. Otherwise specify a path. Examples: */ /* Specify PATH=STAT to modify all STAT templates. */ /* Specify PATH=STAT.REG to modify all PROC REG templates. */ /* Specify PATH=STAT.REG.GRAPHICS.FIT to modify the PROC */ /* REG fit plot template. If any of the templates are */ /* links, the link path is followed, and the final */ /* template is modified. */ /* */ options=, /* OPTIONS=DELETE deletes the modified templates. */ /* OPTIONS=NODELETE does not delete any compiled templates.*/ /* OPTIONS=DISPLAY displays the template NOTES statement */ /* (if there is one) and ENTRYTITLE statments. */ );; /*---------------------------------------------------------*/ /*---------------------------------E X A M P L E---------------------------------- * Modify PROC REG templates; %grtitle(path=stat.reg) * View the report of the template names and the generated macro variables. Here are a few: Stat.Reg.Graphics.DiagnosticsPanel Reg_DiagnosticsPanel Stat.Reg.Graphics.Fit Reg_Fit Stat.Reg.Graphics.FitHeatMap Reg_FitHeatMap Stat.Reg.Graphics.ResidualPanel Reg_ResidualPanel Reg_ResidualPanel2 * Set the macro variables to the titles that you want displayed. Notice that the residual panel has two titles. Other graphs have one. ; * View the modified templates. This step is not required.; proc template; list / store=work.templat; source / store=work.templat; quit; * Set the macro variable before running the procedure to override the title. ods graphics on; %let reg_fit = My Title; proc reg data=sashelp.class; ods select fitplot; model weight = height; quit; * Restore the original templates.; %grtitle(options=delete) ---------------------------------E X A M P L E---------------------------------- %grtitle(path=Stat.Logistic.Graphics.AnomPlot) * The macro reports:; Stat.Logistic.Graphics.AnomPlot -> Stat.Graphics.AnomPlot Graphics_AnomPlot Graphics_AnomPlot2 * This shows that the specified template is a link to another template.; ---------------------------------E X A M P L E---------------------------------- data Neuralgia; input Treatment $ Sex $ Age Duration Pain $ @@; datalines; P F 68 1 No B M 74 16 No P F 67 30 No P M 66 26 Yes B F 67 28 No B F 77 16 No A F 71 12 No B F 72 50 No B F 76 9 Yes A M 71 17 Yes A F 63 27 No A F 69 18 Yes B F 66 12 No A M 62 42 No P F 64 1 Yes A F 64 17 No P M 74 4 No A F 72 25 No P M 70 1 Yes B M 66 19 No B M 59 29 No A F 64 30 No A M 70 28 No A M 69 1 No B F 78 1 No P M 83 1 Yes B F 69 42 No B M 75 30 Yes P M 77 29 Yes P F 79 20 Yes A M 70 12 No A F 69 12 No B F 65 14 No B M 70 1 No B M 67 23 No A M 76 25 Yes P M 78 12 Yes B M 77 1 Yes B F 69 24 No P M 66 4 Yes P F 65 29 No P M 60 26 Yes A M 78 15 Yes B M 75 21 Yes A F 67 11 No P F 72 27 No P F 70 13 Yes A M 75 6 Yes B F 65 7 No P F 68 27 Yes P M 68 11 Yes P M 67 17 Yes B M 70 22 No A M 65 15 No P F 67 1 Yes A M 67 10 No P F 72 11 Yes A F 74 1 No B M 80 21 Yes A F 69 3 No ; * Modify the control plot template. Notice that a different template was modified, which means the original template is a link. When a single template is specified, and that single template is a link, the macro will follow the link and modify the actual underlying graph template.; %grtitle(path=Stat.Logistic.Graphics.AnomPlot) * Make the plot with a modified second title.; ods graphics on; %let Graphics_AnomPlot2 = My Second Title; proc logistic data=Neuralgia; ods select anomplot; class Treatment Sex / param=glm; model Pain= Treatment|Sex Age; lsmeans Treatment / plots=anom; run; * Suppress both titles.; %let Graphics_AnomPlot = ; %let Graphics_AnomPlot2 = ; proc logistic data=Neuralgia; ods select anomplot; class Treatment Sex / param=glm; model Pain= Treatment|Sex Age; lsmeans Treatment / plots=anom; run; * Restore the original templates.; %grtitle(options=delete) ---------------------------------E X A M P L E---------------------------------- * Delete all modified templates and then modify the LOGISTIC templates; %grtitle(path=stat.logistic) * List the modified templates. This is not required.; proc template; list / store=work.templat; quit; * Restore the original templates.; %grtitle(options=delete) * Show that the modified templates have been deleted. This is not required.; proc template; list / store=work.templat; quit; * Display the template search path. WORK.TEMPLAT was inserted.; ods path show; * Display additional information about each template and title. %grtitle(path=stat.glm, options=display) -------------------------------------------------------------------------------- DISCLAIMER: THIS INFORMATION IS PROVIDED BY SAS INSTITUTE INC. AS A SERVICE TO ITS USERS. IT IS PROVIDED "AS IS". THERE ARE NO WARRANTIES, EXPRESSED OR IMPLIED, AS TO MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE REGARDING THE ACCURACY OF THE MATERIALS OR CODE CONTAINED HEREIN. ------------------------------------------------------------------------------*/ %local saveopts abort; %global __savepath; ods; %let saveopts = %sysfunc(getoption(notes)) %sysfunc(getoption(source)); options nonotes nosource; data _null_; length l $ 200; l = ' ' || lowcase(symget('options')); call symputx('delete', index(l, ' delete')); call symputx('nodelete', index(l, 'nodelete')); call symputx('display', index(l, 'display')); call symputx('abort', '0'); l = symget('sysodspath'); l = tranwrd(l, 'WORK.TEMPLAT(UPDATE)', ' '); call symputx('__savepath', l); if _error_ then call symput('abort', '1'); run; %if &syserr > 4 %then %let abort = 1; %if &abort = 1 %then %goto endit; %if not &nodelete %then %do; ods path sashelp.tmplmst(read); proc datasets library=work nolist; delete templat(memtype=itemstor); quit; %if &syserr > 4 %then %let abort = 1; %if &abort = 1 %then %goto endit; %end; %if not &delete %then %do; ods path &__savepath; proc template; ods exclude stats; ods output stats=__s; list &path / where=(type = 'Statgraph' or type = 'Link'); quit; %if &syserr > 4 %then %let abort = 1; %if &abort = 1 %then %goto endit; options nosource; data _null_; set __s; if type in ('Statgraph', 'Link') then call execute(catt('%nrstr(%grtitle2(path=', path, '))')); if _error_ then call symput('abort', '1'); run; options source; %if &syserr > 4 %then %let abort = 1; %if &abort = 1 %then %goto endit; %end; %endit: options &saveopts; ods path work.templat(update) &__savepath; %mend; /*-----------------------------------------------------------------------------*/ %macro grtitle2(path=); %local follow abort; data _null_; call symputx('follow', '0'); call symputx('abort', '0'); if _error_ then call symput('abort', '1'); run; %if &syserr > 4 %then %let abort = 1; %if &abort = 1 %then %goto endit; proc template; source &path / file='temp.temp' where=(type = 'Statgraph' or type = 'Link'); run; %if &syserr > 4 %then %let abort = 1; %if &abort = 1 %then %goto endit; data _null_; infile 'temp.temp'; input; if _n_ = 1 then call symputx('follow', scan(lowcase(_infile_), 1, ' ') = 'link'); if _n_ > 1 then do; call symputx('follow', 0); stop; end; if _error_ then call symput('abort', '1'); run; %if &syserr > 4 %then %let abort = 1; %if &abort = 1 %then %goto endit; %if &follow %then %do; %do i = 1 %to 10; data _null_; infile 'temp.temp'; input; if scan(lowcase(_infile_), 1, ' ') = 'link' then call execute(catx(' ', 'proc template; source', scan(_infile_, 4, ' ;'), "/ file='temp.temp'; run;")); else call symputx('i', 11); stop; if _error_ then call symput('abort', '1'); run; %if &syserr > 4 %then %let abort = 1; %if &abort = 1 %then %goto endit; %end; %end; ods path work.templat(update) &__savepath; data _null_; infile 'temp.temp'; input; length macrovar $ 80 name $ 200 l $ 256; retain macrovar; if _n_ = 1 then call execute('proc template;'); if index(_infile_, 'define table') then do; call execute('quit;'); stop; end; if index(_infile_, 'define statgraph') then do; name = scan(_infile_, 3, ' ;'); if "&path" ne name then put / "&path -> " name; else put / name; n = 0; macrovar = cats(scan(_infile_, 4, ' .;'), '_', scan(_infile_, -1, ' .;')); if length(macrovar) gt 31 then macrovar = scan(_infile_, -1, ' .;'); substr(macrovar, 32) = ' '; end; if &display and left(lowcase(_infile_)) =: 'notes ' then do; l = left(_infile_); put ' ' l; end; if left(lowcase(_infile_)) =: 'entrytitle' and not index(_infile_, '_BYLINE_') then do; n + 1; name = cats(macrovar, ifc(n = 1, ' ', n)); put %if &display %then /; ' ' name; if &display then do; l = left(_infile_); put ' ' l; end; call execute(catx(' ', 'mvar', name, ';')); call execute(catx(' ', 'if (exists(', name, ')) entrytitle', name, '; else')); call execute(catt(_infile_, ' endif;')); end; else call execute(_infile_); if scan(lowcase(_infile_), 1, ' ') = 'link' then put / _infile_; if _error_ then call symput('abort', '1'); run; %if &syserr > 4 %then %let abort = 1; %if &abort = 1 %then %goto endit; ods path &__savepath; proc datasets nolist; delete __s; quit; %endit: %mend;