%let name=gage; filename odsout '.'; /* This is a custom gage chart, created using good-old traditional sas/graph technology - namely annotated 'pies', lines and text. The pie is created by specifying the values for the start-angle and end-angle, and color, for each colored range/segment (you specify these as the 'segment's in the data set below), and also an observation in the dataset for the 'arrow' (this is the pointer/arrow for the gage). */ %macro do_gage(mydata, major_by, minor_by, titletext, foottext); %local mydata major_by minor_by titletext foottext; proc sql noprint; select min(start) into :min_start from &mydata where grtype eq 'segment'; select max(end) into :max_end from &mydata where grtype eq 'segment'; select min(start) into :arrow_val from &mydata where grtype eq 'arrow'; quit; run; data ranges arrow text; length html $500; length text $100; length function color $ 8; length style $ 15; set &mydata; xsys='3'; ysys='3'; hsys='3'; when='A'; /* Draw color range segments */ if grtype eq 'segment' then do; x=50; y=50; size=32; function='PIE'; style='PSOLID'; min_start=&min_start; max_end=&max_end; percent_start=((start-&min_start)/(&max_end-&min_start)); percent_end=((end-&min_start)/(&max_end-&min_start)); angle_start=240-((start-&min_start)/(&max_end-&min_start))*300; angle_end=240-((end-&min_start)/(&max_end-&min_start))*300; angle=angle_end; rotate= (240-((start-&min_start)/(&max_end-&min_start))*300) - (240-((end-&min_start)/(&max_end-&min_start))*300) ; output ranges; end; else if grtype eq 'arrow' then do; x=50; y=50; size=32; function='PIE'; when='b'; style='PSOLID'; /* real pie slice is invisible/behind */ angle=240-((start-&min_start)/(&max_end-&min_start))*300; rotate=.1; output arrow; function='piexy'; size=1; /* With piexy size is the 'multiplier' for the previous pie's size */ output arrow; x=50; y=50; when='a'; function='draw'; size=.5; /* size is width of line now */ output arrow; /* And, write the number at the bottom & top of the pie - do this when you write the arrow, so you do it only once. */ function='label'; color="black"; style='"arial/bold"'; angle=0; rotate=0; position='5'; size=6; y=98; text="&titletext"; output text; y=5; text="&foottext: "||trim(left(start)); output text; end; run; data behind middle front hub; length function color $ 8; length style $ 15; xsys='3'; ysys='3'; hsys='3'; when='A'; x=50; y=50; length html $ 200; html='title='||quote( trim(left("&arrow_val"))) ||' '|| 'href="panel.htm"'; function='PIE'; style='PSOLID'; angle=0; rotate=360; color="cx36648B"; size=42; output behind; /* outer border */ html=''; color="cx33A1C9"; size=41; output behind; /* outer color swatch/ring */ color="cx36648B"; size=36; output behind; /* inner color border */ color="cxdddddd"; size=35; output behind; /* gray area */ color="cxdddddd"; size=29; output middle; /* gray area, inside colored ranges */ color="cxdddddd"; size=27.5; output front; /* innermost gray area (chops the major tickmarks) */ color="white"; size=2; output hub; /* white center */ color="black"; size=2; style="pempty"; output hub; /* black ring around white center */ run; data minorticks; length text $100; length function color $ 8; length style $ 15; xsys='3'; ysys='3'; hsys='3'; do tick = &min_start to &max_end by &minor_by; x=50; y=50; size=32; function='PIE'; when='b'; style='pempty'; /* real pie slice is invisible/behind */ angle=240-((tick-&min_start)/(&max_end-&min_start))*300; rotate=.1; output; function='piexy'; size=1; output; x=50; y=50; color="gray66"; when='a'; function='draw'; size=.1; output; end; run; data majorticks; length text $100; length function color $ 8; length style $ 15; xsys='3'; ysys='3'; hsys='3'; do tick = &min_start to &max_end by &major_by; x=50; y=50; size=32; function='PIE'; when='b'; style='pempty'; /* real pie slice is invisible/behind */ angle=240-((tick-&min_start)/(&max_end-&min_start))*300; rotate=.1; output; function='piexy'; size=1; output; x=50; y=50; color="black"; when='a'; function='draw'; size=.1; output; end; run; data majornums; length text $100; length function color $ 8; length style $ 15; xsys='3'; ysys='3'; hsys='3'; do tick = &min_start to &max_end by &major_by; x=50; y=50; size=32; function='PIE'; when='b'; style='pempty'; /* real pie slice is invisible/behind */ angle=240-((tick-&min_start)/(&max_end-&min_start))*300; rotate=.1; output; function='piexy'; size=.75; output; function='cntl2txt'; output; function='label'; when='a'; text=trim(left(tick)); angle=0; rotate=0; position='5'; style='"arial/bold"'; size=3.25; x=.; y=.; output; end; run; data gageanno; set behind ranges minorticks middle majorticks front majornums arrow hub text; run; proc ganno annotate=gageanno des="" name="&name"; run; /* proc print data=gageanno; run; */ %mend do_gage; GOPTIONS DEVICE=gif; ODS LISTING CLOSE; ODS HTML path=odsout body="&name..htm" (title="Custom Gage Chart") style=minimal gtitle gfootnote ; goptions border; goptions hsize=5in vsize=5in; options mprint; /* %macro do_gage(mydata, major_by, minor_by, titletext, foottext); */ data my_data; length grtype color $ 8; input grtype color start end; cards; segment cx00cd00 0 6000 segment orange 6000 6600 segment cxff0000 6600 8000 arrow black 5700 5700 ; run; %do_gage(my_data,1000,200,Tachometer,Current RPM); data my_data2; length grtype color $ 8; input grtype color start end; cards; segment cxff0000 0 50 segment cx00cd00 50 100 arrow black 11 11 ; run; %do_gage(my_data2,10,5,Scheduling,Percent Bid When Scheduled); data my_data3; length grtype color $ 8; input grtype color start end; cards; segment cyan -100 0 segment red 0 100 segment orange 100 200 segment yellow 200 300 segment green 300 400 segment blue 400 500 segment indigo 500 600 segment violet 600 700 arrow magenta 223 223 ; run; %do_gage(my_data3,100,20,Rainbow,Happy Value); data my_data4; length grtype color $ 8; input grtype color start end; cards; segment cx87CEFF -25 32 segment cx00EE00 32 85 segment cxFF4040 85 125 arrow purple 32 32 ; run; %do_gage(my_data4,25,5,Thermometer,Degrees Fahrenheit); quit; ODS HTML CLOSE; ODS LISTING;