/* SAS program to accompany the article "A SAS programming technique to modify ODS templates" by Rick Wicklin. Published 30OCT2017 on The DO Loop blog https://blogs.sas.com/content/iml/2017/10/30/programming-modify-ods-templates.htm */ /* write HEATMAP template to WORK.TEMPLAT */ ods path (prepend) work.templat(update); proc template; /* basic heat map with continuous color ramp */ define statgraph HEATMAP; dynamic _X _Y _Z; /* dynamic variables */ begingraph; layout overlay; heatmapparm x=_X y=_Y colorresponse=_Z / /* specify variables at run time */ name="heatmap" primary=true xbinaxis=false ybinaxis=false colormodel = THREECOLORRAMP; /* <== hard-coded color ramp */ continuouslegend "heatmap"; endlayout; endgraph; end; run; data Cubic; /* A cubic function of z = f(x,y) on regular grid */ do x = -1 to 1 by 0.04; do y = -1 to 1 by 0.04; z = x**3 - y**2 - x + 0.5; output; end; end; run; proc sgrender data=Cubic template=HEATMAP; dynamic _X='X' _Y='Y' _Z='Z'; run; ods path show; proc template; list HEATMAP; run; /***************************************************/ /* begin Kuhfeld's template modification technique */ /***************************************************/ /* This example changes the color ramp AT RUN TIME. 1. Modify the search path for ODS. Prepend an item store in WORK 2. Write template to text file. 3. Replace 'TWOCOLORRAMP' with new choice. 4. Compile (modified) template. Write modified template to WORK.IMLTMPL. 5. Call PROC SGRENDER on new template. */ /* 1. Modify the search path for ODS. Prepend an item store in WORK */ ods path (prepend) work.modtemp(update); ods path show; /* 2. Write existing template to text file. The text file does not start with PROC TEMPLATE or end with RUN; it contains the body of the template */ *filename _tmplt "C:/temp/tmplt.txt"; /* hard-coded name */ filename _tmplt TEMP; /* create temporary file and name */ proc template; source HEATMAP / file=_tmplt; /* write template source to text file */ run; /* possible ways to specify a new color ramp */ %let NEWCOLORRAMP = TwoColorRamp; %let NEWCOLORRAMP = (CX352A86 CX1483D4 CX33B8A0 CXD2BA58 CXF8FA0D); %let NEWCOLORRAMP = (blue cyan yellow red); /* 3. Read old template; make modifications. 4. Use CALL EXECUTE to compile (modified) template with new name. */ data _null_; /* Modify graph template to replace default color ramp */ infile _tmplt end=eof; /* read from text file */ input; /* read one line at a time */ if _n_ = 1 then call execute('proc template;'); /* add 'PROC TEMPLATE;' before */ if findw(_infile_, 'define statgraph') then _infile_ = "define statgraph NEWHEATMAP;"; /* optional: assign new template name */ /* use TRANWRD to make substitutions here */ _infile_ = tranwrd(_infile_, 'THREECOLORRAMP', "&NEWCOLORRAMP"); /* replace COLORMODEL= option */ call execute(_infile_); /* push line onto stack; compile after DATA step */ if eof then call execute('run;'); /* add 'RUN;' at end */ run; /* Is the new template correct? Is it in the correct location? */ proc template; list NEWHEATMAP / stats=created; /* location of the modified template */ source NEWHEATMAP; /* confirm that substitutions were performed */ run; /* 5. Call PROC SGRENDER on new template */ proc sgrender data=Cubic template=NEWHEATMAP; dynamic _X='X' _Y='Y' _Z='Z'; run; /* if you want to delete your modified version */ /* proc template; delete NEWHEATMAP / store=work.modtemp; run; proc template; list / store=work.templat; run; */