I've just got my hands on Stephen Few's "Show me the numbers" and wanted to implement to most basics advice automatically by creating a template/style. I created a PROC TEMPLATE program that creates such a style; here are some samples of the result.
It's not perfect, but here's my template program, along with examples of use with proc report and proc sgplot.
%macro hex2(n);
%local digits n1 n2;
%let digits = 0123456789ABCDEF;
%let n1 = %substr(&digits, &n / 16 + 1, 1);
%let n2 = %substr(&digits, &n - &n / 16 * 16 + 1, 1);
&n1&n2
%mend hex2;
/* convert RGB triplet (r,g,b) to SAS color in hexadecimal.
The r, g, and b parameters are integers in the range 0--255 */
%macro RGB(r,g,b);
%cmpres(CX%hex2(&r)%hex2(&g)%hex2(&b))
%mend RGB;
*** light is used for large data objects, such as a bar or box;
%let lightgrey = %rgb(140,140,140);
%let lightblue = %rgb(136,189,230);
%let lightorange = %rgb(251,178,88);
%let lightgreen = %rgb(144,205,151);
%let lightpink = %rgb(246,170,201);
%let lightbrown = %rgb(191,165,84);
%let lightpurple = %rgb(188,153,199);
%let lightyellow = %rgb(237,221,70);
%let lightred = %rgb(240,126,110);
*** medium is used for small data objects such as data points and lines;
%let mediumgrey = %rgb(77,77,77);
%let mediumblue = %rgb(93,165,218);
%let mediumorange = %rgb(250,164,58);
%let mediumgreen = %rgb(96,189,104);
%let mediumpink = %rgb(241,124,176);
%let mediumbrown = %rgb(178,145,47);
%let mediumpurple = %rgb(178,118,178);
%let mediumyellow = %rgb(222,207,63);
%let mediumred = %rgb(241,88,84);
*** dark and bright highlighter is used for objects, such as a single bar;
%let darkgrey = %rgb(0,0,0);
%let darkblue = %rgb(38,93,171);
%let darkorange = %rgb(223,92,36);
%let darkgreen = %rgb(5,151,72);
%let darkpink = %rgb(229,18,111);
%let darkbrown = %rgb(157,114,42);
%let darkpurple = %rgb(123,58,150);
%let darkyellow = %rgb(199,180,46);
%let darkred = %rgb(203,32,39);
proc template;
define style Styles.Custom;
parent = Styles.RTF;
replace fonts /
'TitleFont' = ("Tahoma",14pt,Bold) /* Titles from TITLE statements */
'TitleFont2' = ("Tahoma",14pt,Bold) /* Procedure titles ("The _____ Procedure")*/
'StrongFont' = ("Tahoma",10pt,Bold)
'EmphasisFont' = ("Tahoma",10pt,Italic)
'headingEmphasisFont' = ("Tahoma",10pt,Italic)
'headingFont' = ("Tahoma",10pt) /* Table column and row headings */
'docFont' = ("Tahoma",10pt) /* Data in table cells */
'footFont' = ("Tahoma",8pt) /* Footnotes from FOOTNOTE statements */
'FixedEmphasisFont' = ("Courier",10pt,Italic)
'FixedStrongFont' = ("Courier",10pt,Bold)
'FixedHeadingFont' = ("Courier",10pt,Bold)
'BatchFixedFont' = ("Courier",7pt)
'FixedFont' = ("Courier",10pt);
replace color_list /
'link' = &darkblue. /* links */
'bgH' = white /* row and column header background */
'fg' = black /* text color */
'bg' = white; /* page background color */;
replace Body from Document /
bottommargin = 0.25in
topmargin = 0.25in
rightmargin = 0.25in
leftmargin = 0.25in;
replace Table from Output /
frame = void /* outside borders: void, box, above/below, vsides/hsides, lhs/rhs */
rules = groups /* internal borders: none, all, cols, rows, groups */
cellpadding = 3pt /* the space between table cell contents and the cell border */
cellspacing = 0pt /* the space between table cells, allows background to show */
borderwidth = 2pt /* the width of the borders and rules */;
* Leave code below this line alone ;
style SystemFooter from SystemFooter /
font = fonts("footFont");
* mon code a moi;
replace GraphFonts /
'GraphDataFont'=("Tahoma",10pt)
'GraphUnicodeFont'=("Tahoma",10pt)
'GraphValueFont'=("Tahoma",10pt)
'GraphLabelFont'=("Tahoma",10pt)
'GraphLabel2Font'=("Tahoma",10pt)
'GraphFootnoteFont'=("Tahoma",8pt)
'GraphTitleFont'=("Tahoma",14pt)
'GraphTitle1Font'=("Tahoma",14pt)
'GraphAnnoFont'=("Tahoma",10pt)
;
replace colors
/* "Abstract colors used in the default style" *//
'headerfgemph' = color_list('fg')
'headerbgemph' = color_list('bgH')
'headerfgstrong' = color_list('fg')
'headerbgstrong' = color_list('bgH')
'headerfg' = color_list('fg')
'headerbg' = color_list('bgH')
'datafgemph' = color_list('fg')
'databgemph' = color_list('bg')
'datafgstrong' = color_list('fg')
'databgstrong' = color_list('bg')
'datafg' = color_list('fg')
'databg' = color_list('bg')
'batchbg' = color_list('bg')
'batchfg' = color_list('fg')
'tableborder' =&mediumgrey.
'tablebg' = color_list('bg')
'notefg' = color_list('fg')
'notebg' = color_list('bg')
'bylinefg' = color_list('fg')
'bylinebg' = color_list('bg')
'captionfg' = color_list('fg')
'captionbg' = color_list('bg')
'proctitlefg' = color_list('fg')
'proctitlebg' = color_list('bg')
'titlefg' = color_list('fg')
'titlebg' = color_list('bg')
'systitlefg' = color_list('fg')
'systitlebg' = color_list('bg')
'Conentryfg' = color_list('fg')
'Confolderfg' = color_list('fg')
'Contitlefg' = color_list('fg')
'link2' = color_list('link')
'link1' = color_list('link')
'contentfg' = color_list('fg')
'contentbg' = color_list('bg')
'docfg' = color_list('fg')
'docbg' = color_list('bg');
replace GraphColors /
/*"Abstract colors used in graph styles" */
'ginsetheader' = colors('docbg')
'ginset' = white
'greferencelines' = &mediumgrey.
'gheader' = colors('docbg')
'gtext' = &mediumgrey.
'glabel' = &mediumgrey.
'gborderlines' = &mediumgrey.
'goutlines' = &mediumgrey.
'ggrid' = &lightgrey.
'gaxis' = &lightgrey.
'gshadow' = &lightgrey.
'glegend' = white
'gfloor' = white
'gwalls' = _undef_
'gcdata1' = &mediumblue.
'gcdata2' = &mediumorange.
'gcdata3' = &mediumgreen.
'gcdata4' = &mediumpink.
'gcdata5' = &mediumbrown.
'gcdata6' = &mediumpurple.
'gcdata7' = &mediumyellow.
'gcdata8' = &mediumred.
'gcdata9' = &mediumgrey.
'gcdata10' = &darkblue.
'gcdata11' = &darkorange.
'gcdata12' = &darkred.
'gdata1' = &mediumgrey.
'gdata2' = &mediumgrey.
'gdata3' = &mediumgrey.
'gdata4' = &mediumgrey.
'gdata5' = &mediumgrey.
'gdata6' = &mediumgrey.
'gdata7' = &mediumgrey.
'gdata8' = &mediumgrey.
'gdata9' = &mediumgrey.
'gdata10' = &mediumgrey.
'gdata11' = &mediumgrey.
'gdata12' = &mediumgrey.
'gcmiss' = &lightgrey.
'gmiss' = &lightgrey.
'gablock' = cxF1F0F6
'gblock' = cxD7DFEF
'gcclipping' = cxDC531F
'gclipping' = cxE7774F
'gcstars' = &mediumgrey.
'gstars' = cxB9CFE7
'gcruntest' = cxBF4D4D
'gruntest' = cxCAE3FF
'gccontrollim' = cxBFC7D9
'gcontrollim' = cxE6F2FF
'gcerror' = &mediumgrey.
'gerror' = cxB9CFE7
'gcpredictlim' = cx003178
'gpredictlim' = cxB9CFE7
'gcpredict' = cx003178
'gpredict' = cx003178
'gcconfidence2' = cx003178
'gcconfidence' = cx003178
'gconfidence2' = cxB9CFE7
'gconfidence' = cxB9CFE7
'gcfit2' = cx003178
'gcfit' = cx003178
'gfit2' = cx003178
'gfit' = cx003178
'gcoutlier' = &mediumgrey.
'goutlier' = cxB9CFE7
'gcdata' = &mediumgrey.
'gdata' = cxB9CFE7
'gconramp3cend' = cxFF0000
'gconramp3cneutral' = cxFF00FF
'gconramp3cstart' = cx0000FF
'gramp3cend' = cxDD6060
'gramp3cneutral' = white
'gramp3cstart' = cx6497EB
'gconramp2cend' = cx6497EB
'gconramp2cstart' = white
'gramp2cend' = cx5E528B
'gramp2cstart' = cxEDEBF6
;
class graphwalls /
frameborder=off;
class graphbackground /
color=white;
style GraphData1 from GraphData1 /linestyle=1 markersymbol = "circle";
style GraphData2 from GraphData2 /linestyle=1 markersymbol = "circle";
style GraphData3 from GraphData3 /linestyle=1 markersymbol = "circle";
style GraphData4 from GraphData4 /linestyle=1 markersymbol = "circle";
style GraphData5 from GraphData5 /linestyle=1 markersymbol = "circle";
style GraphData6 from GraphData6 /linestyle=1 markersymbol = "circle";
style GraphData7 from GraphData7 /linestyle=1 markersymbol = "circle";
style GraphData8 from GraphData8 /linestyle=1 markersymbol = "circle";
style GraphData9 from GraphData9 /linestyle=1 markersymbol = "circle";
style GraphData10 from GraphData10 /linestyle=1 markersymbol = "circle";
style GraphData11 from GraphData11 /linestyle=1 markersymbol = "circle";
style GraphData12 from GraphData12 /linestyle=1 markersymbol = "circle";
style GraphBorderLines from GraphBorderLines /
LineThickness=0;
style GraphBackground / transparency=1 ;
end;
run;
/* Sample program that shows the output */
%let very_light_grey=E2EDF4;
ods rtf file="c:\temp\report.rtf" style=styles.custom;
OPTIONS NODATE NONUMBER;
ods escapechar = '^';
title1
j=c "Title" ;
title2
j=c "Subtitle";
*note : the trick for the header columns spanned from Beyond the Basics: Advanced PROC REPORT Tips and Tricks ";
footnote1 j=l "Footnote1";
footnote2 j=l "Footnote2";
proc sort data= sashelp.class out=temp;; by sex height weight;
run;
data temp;
set temp;
by sex;
if first.sex then sex2= sex;
else sex2="";
obs=_n_;
weight_cat= floor(weight/10)*10;
run;
proc report data=temp ls=120 ps=40 nowd
split="*"
style(report)=
[]
style(header)=
[just=l];
column
obs
sex2
name
("^S={just=c borderbottomcolor=&lightgrey.} Metrics^{super 1}" height weight )
row_color
;
define obs /display noprint;
define sex2/display "Sex" style(header)=[just=l borderbottomcolor=&lightgrey.] style(column)=[just=l];
define name /display "Name" style(header)=[just=l borderbottomcolor=&lightgrey.] style(column)=[just=l];
define height/display "Height" format =5.1 style(header)=[just=r borderbottomcolor=&lightgrey.] style(column)=[just=r];
define weight /display "Weight^{super 2}" format =5.0 style(header)=[just=r borderbottomcolor=&lightgrey.] style(column)=[just=r ] format=16.;
define row_color /computed noprint;
compute row_color;
if mod(obs,2)=1 then call define (_row_,"style","style=[background=#&very_light_grey.]");
endcomp;
run;
quit;
ods rtf text=
"^S={fontsize = 8pt color=&lightgrey.} ^{newline}
Notes: ^{newline}
1. Some note about the metrics. ^{newline}
2. Some note about the weight."
;
ods graphics / reset=all border=off width=6in height=4in;
proc sgplot data= temp;
scatter x=weight y=height /group=sex;
run;
proc sql;
create table for_graph as
select distinct sex, weight_cat, count(*) as count
from temp
group by sex,weight_cat
;
quit;
data for_graph3;
set for_graph;
by sex;
if last.sex then datalabel=sex;
run;
proc format ;
value weightcatf
50="50-60"
60="60-70"
70="70-80"
80="80-90"
90="90-100"
100="100-110"
110="110-120"
120="120-130"
130="130-140"
140="140-150"
150="150-160"
;
run;
proc sgplot data=for_graph3 noautolegend;
series x=weight_cat y=count /group=sex datalabel=datalabel;
yaxis values=(0 to 4 by 1) label="Count";
xaxis values=(50 to 150 by 10) label ="Weight category";
title "Count by sex and weight category";
format weight_cat weightcatf.;
run;
title;
ods rtf close;
Thanks to @Reeza who has also shared the program on GitHub
https://gist.github.com/statgeek/9845cc3d26e4c35e01a2
... View more