%let name=fundrais; filename odsout '.'; /* I started with data from examples on the iDashes website... http://www.visualmining.com/developers/application-examples.shtml And then tried to make a dashboard that was more functional than theirs :) */ data rawrev; input attribute $ 1-20 FY2000 FY2001 FY2002 FY2003 FY2004 FY2005; format FY2000 FY2001 FY2002 FY2003 FY2004 FY2005 dollar20.2; amttype='Revenue'; datalines; Annual Fund 191000.00 229200.00 275040.00 330048.00 396057.60 475269.00 Special Events 198500.00 176620.00 215600.00 192110.00 199890.00 201560.00 Planned Giving . . . . . 100000.00 Car Donations 13000.00 13650.00 14322.50 15049.12 15081.58 16591.66 In-Kind Donations 172000.00 175000.00 175000.00 175000.00 175000.00 175000.00 Total Unrestricted 576000.00 617850.00 664372.50 720097.12 786859.18 966860.78 Restricted Grants 340000.00 . . . . . ; run; data rawexp; input attribute $ 1-20 FY2000 FY2001 FY2002 FY2003 FY2004 FY2005; format FY2000 FY2001 FY2002 FY2003 FY2004 FY2005 dollar20.2; amttype='Expense'; datalines; Personnel 348512.00 350000.00 358512.00 358512.00 340000.00 345000.00 Non Personnel 130000.00 100000.00 100000.00 100000.00 110000.00 100000.00 Direct Allocated 80000.00 80000.00 80000.00 80000.00 90000.00 90000.00 G&A 20000.00 20000.00 20000.00 20000.00 20000.00 45000.00 ; run; data rawdata; set rawrev rawexp; run; proc sql; create table totrev as select unique 'Totals' as amttype, 'Total Revenue ' as attribute, sum(FY2000) format=dollar20.2 as FY2000, sum(FY2001) format=dollar20.2 as FY2001, sum(FY2002) format=dollar20.2 as FY2002, sum(FY2003) format=dollar20.2 as FY2003, sum(FY2004) format=dollar20.2 as FY2004, sum(FY2005) format=dollar20.2 as FY2005 from rawrev; create table totexp as select unique 'Totals' as amttype, 'Total Expenses' as attribute, sum(FY2000) format=dollar20.2 as FY2000, sum(FY2001) format=dollar20.2 as FY2001, sum(FY2002) format=dollar20.2 as FY2002, sum(FY2003) format=dollar20.2 as FY2003, sum(FY2004) format=dollar20.2 as FY2004, sum(FY2005) format=dollar20.2 as FY2005 from rawexp; create table cost as select unique 'Totals' as amttype, 'Cost per $' as attribute, (totexp.FY2000 / totrev.FY2000) format=dollar20.2 as FY2000, (totexp.FY2001 / totrev.FY2001) format=dollar20.2 as FY2001, (totexp.FY2002 / totrev.FY2002) format=dollar20.2 as FY2002, (totexp.FY2003 / totrev.FY2003) format=dollar20.2 as FY2003, (totexp.FY2004 / totrev.FY2004) format=dollar20.2 as FY2004, (totexp.FY2005 / totrev.FY2005) format=dollar20.2 as FY2005 from totexp left join totrev on totexp.amttype = totrev.amttype; quit; run; proc sort data=rawdata out=rawdata; by amttype attribute; run; proc transpose data=rawdata out=trandata; by amttype attribute; run; data trandata; set trandata; year=0; year=substr(_name_,3,4); run; proc transpose data=cost out=trancost; by attribute; run; data trancost; set trancost; year=0; year=substr(_name_,3,4); run; /* Create custom template, to get rid of page separator (horizontal rule/line after graph) */ proc template; define style styles.mystyle; parent=styles.statdoc; style body from body / pagebreakhtml=_undef_; end; run; GOPTIONS DEVICE=gif; ODS LISTING CLOSE; ODS HTML path=odsout body="&name..htm" (title="Fundraising Dashboard") style=mystyle /* style=journal */ ; goptions noborder; goptions gunit=pct htitle=8 ftitle="arial/bold" htext=4 ctext=purple ftext="arial"; goptions colors=(purple); goptions nodisplay; /* Cback doesn't seem to work with greplay, so I'm annotating the background color instead... */ data purple_anno; length function $8 style color $10; retain xsys '3' ysys '3' when 'b' style 'solid'; function='move'; x=0; y=0; output; function='bar'; x=100; y=100; color="purple"; output; run; title1 h=22pct " "; title2 ls=3 c=white h=15pct f="arial/bold/italic" "Raise More"; title3 ls=3 c=white h=15pct f="arial/bold/italic" "Capital !"; proc gslide name='titl1' anno=purple_anno; run; quit; pattern1 v=s c=purple; pattern2 v=s c=cxaeadd9; axis1 label=none major=(number=5) minor=none offset=(0,0); axis2 label=none value=none; axis3 label=none; legend1 label=none shape=bar(3,4); title ls=3 "Revenue & Expenses"; title2 a=-90 h=3 " "; footnote; /* pre-summarize the data, so you can have chart tips */ proc sql noprint; create table sumdata as select unique amttype, year, sum(col1) as col1 from trandata group by amttype, year; quit; run; data sumdata; set sumdata; length htmlvar $500; htmlvar='title='||quote( 'Year '|| trim(left(year)) || ' ' || trim(left(amttype)) ||' = '|| trim(left(put(col1,dollar12.0))) ) ||' '|| 'href="fundrais.htm"'; run; proc gchart data=sumdata; format col1 dollar12.0; vbar amttype / type=sum sumvar=col1 subgroup=amttype group=year space=0 gspace=3 raxis=axis1 maxis=axis2 gaxis=axis3 legend=legend1 coutline=gray autoref cref=graycc lref=2 clipref html=htmlvar name='barplot'; run; data gantdata; length event $ 30; event='Summer Fest'; start='01jul05'd; end='14jul05'd; output; event='Direct Mail'; start='01jun05'd; end='30jun05'd; output; event='Mall Booth'; start='15nov05'd; end='30dec05'd; output; event='Web Page'; start='01jan05'd; end='30dec05'd; output; event='Spring Fling'; start='01apr05'd; end='30may05'd; output; event='Telethon'; start='01feb05'd; end='07feb05'd; output; event='Rib Cookoff'; start='05oct05'd; end='07oct05'd; output; event="Semi-Formal"; start='14feb05'd; end='15feb05'd; output; event="Jail-A-Thon"; start='03aug05'd; end='07aug05'd; output; run; data gantdata; set gantdata; length htmlvar $500; htmlvar='title='||quote( trim(left(event)) || ' (' || trim(left(lowcase(put(start,date7.)))) ||'-'|| trim(left(lowcase(put(end,date7.)))) || ')' ) ||' '|| 'href="fundrais.htm"'; sub='invis'; value=start; output; sub='vis'; value=end-start; output; run; axis1 order=('01jan05'd to '01jan06'd by month) value=(angle=90) label=none; axis2 label=none value=(justify=right); pattern1 v=s c=white; pattern2 v=s c=cxaeadd9; title ls=3 "Schedule of Fundraising Events (2005)"; title2 a=90 h=5pct " "; title3 a=-90 h=5pct " "; footnote h=3pct " "; proc gchart data=gantdata; format value monname3.; hbar event / type=sum sumvar=value subgroup=sub raxis=axis1 maxis=axis2 coutline=same nostats nolegend autoref cref=graycc lref=1 html=htmlvar name='gantt' ; run; title ls=3 "Cost To Raise A Dollar"; title2 a=-90 h=5 " "; footnote h=3 " "; data trancost; set trancost; length htmlvar $500; htmlvar='title='||quote( 'Year '|| trim(left(year)) || ' ' || 'Cost-per-Dollar: '|| trim(left(put(col1,dollar5.2))) ) ||' '|| 'href="fundrais.htm"'; run; data color_rang; length function $8 style color $10; retain xsys '1' ysys '2' when 'b' style 'solid'; function='move'; x=0; y=0; output; function='bar'; x=100; y=.40; color="cxaddd8e"; output; function='move'; x=0; y=.40; output; function='bar'; x=100; y=.60; color="cxf768a1"; output; run; goptions htitle=12 ftitle="arial/bold" htext=7 ctext=purple ftext="arial"; axis1 order=(0 to .6 by .2) offset=(0,0) minor=none label=none; axis2 minor=none offset=(2,2) label=none; symbol1 ci=purple cv=purple font="arial/bold" v='$' h=10 w=1 i=join; proc gplot data=trancost; format col1 dollar5.2; plot col1*year=1 / vaxis=axis1 haxis=axis2 autovref cvref=gray lvref=2 html=htmlvar anno=color_rang name='costplot'; run; /* I'm creating a Critical Success Factor (CSF) chart by hand, using annotated pie slices. Ideally I would use the java csf applet, but since there is no proc and no grseg I can't use that with greplay. */ proc sql noprint; create table thisyear as select 'arrow' as grtype, 'purple' as color, col1 as value from trancost where year eq 2005; quit; run; /* A little tricky - these are the values of the pie slices/ranges. The green segment is $.00 to $.40 (ie, .40) and the red segment is $.40 to $.60 (which is '$.20' more more in addition to the green segment). */ data csfdata; length grtype color $ 8; input grtype color value; cards; segment cxf768a1 .20 segment cxaddd8e .40 ; run; data csfdata; set csfdata thisyear; run; proc sql noprint; select sum(value) into :sum_val from csfdata where grtype eq 'segment'; quit; run; data gaugtmp; set csfdata; valpct=(value/&sum_val); cumpct+valpct; seg_start=cumpct - valpct; run; data gaugano; length html $500; length text $100; length function color $ 8; length style $30; set gaugtmp; xsys='3'; ysys='3'; hsys='3'; when='A'; length html $500; html='title='||quote( 'Year 2005 Cost per Dollar = $.30' || '0d'x || '(target range < $.40)' ) ||' '|| 'href="fundrais.htm"'; /* Draw pie segments */ if grtype eq 'segment' then do; x=50; y=20; size=50; function='PIE'; style='PSOLID'; angle=(seg_start*180); rotate=(valpct*180); output; end; else if grtype eq 'arrow' then do; /* Draw the indicator */ /* Currently, I'm using a very narrow pie slice - ideally, I would use a line with arrowhead at the top */ when='b'; /* draw a thin pie slice behind/invisible, just to position cursor to draw line */ x=50; y=20; size=50; function='PIE'; style='PSOLID'; angle=((valpct*180)-180)*-1; rotate=.1; output; /* Similar to democd19/panel.sas - foofoo */ function='piexy'; size=1; /* With piexy size is the 'multiplier' for the previous pie's size */ output; when='a'; x=50; y=20; function='draw'; size=.1; /* size is width of line now */ output; /* And, write the number at the bottom of the pie */ function='label'; y=16; size=9; style="arial/bold"; angle=0; position='5'; text=trim(left(put(value,dollar5.2))); output; end; run; goptions xpixels=60 ypixels=50; title ls=3 "Cost per Dollar"; title2 h=8 "(year=2005)"; proc gslide name='csfplot' anno=gaugano; run; title; goptions display; goptions xpixels=785 ypixels=425; %let grborder=gray; proc greplay tc=tempcat nofs igout=gseg; tdef dashbard des='Dashboard' 1/llx = 0 lly = 60 ulx = 0 uly = 100 urx =25 ury = 100 lrx =25 lry = 60 color=&grborder 2/llx =25 lly = 60 ulx =25 uly = 100 urx =75 ury = 100 lrx =75 lry = 60 color=&grborder 3/llx =75 lly = 60 ulx =75 uly = 100 urx =100 ury = 100 lrx =100 lry = 60 color=&grborder 4/llx = 0 lly = 0 ulx = 0 uly = 60 urx =50 ury = 60 lrx =50 lry = 0 color=&grborder 5/llx =50 lly = 0 ulx =50 uly = 60 urx =100 ury = 60 lrx =100 lry = 0 color=&grborder ; template=dashbard; treplay 1:titl1 2:costplot 3:csfplot 4:gantt 5:barplot des="" name="&name" ; run; quit; proc report data=rawdata style(header)=[foreground=white background=purple] style(summary)=[foreground=cx3e3d73 background=cxaeadd9] ; column amttype attribute FY2000 FY2001 FY2002 FY2003 FY2004 FY2005; define amttype / group ' ' style=[foreground=white background=purple]; define attribute / group ' ' style=[foreground=white background=purple]; break after amttype / summarize /* skip */ suppress; run; quit; ODS HTML CLOSE; ODS LISTING;