November, 2007
by Phil Mason
ABSTRACT
SAS® 9 has many new features, as well as
all the old ones. This paper is the
second part of a three part series which will outline some of the best new
features that I have found over the last 3 years that I have been using SAS
9. In the first part I discussed the
Data Step Features. In this part I’ll
cover the ODS and Graph Features. Part 3
will discuss Macro, SQL, and some miscellaneous features.
Introduction
The paper is based on a series of tips
& techniques that I publish to a list of subscribers to my newsletter (see www.woodstreet.org.uk). Since this is a
hands on workshop I will outline the feature we are looking at, and then we
will follow through some example code to see how the feature works and what can
be varied. Remember that the tips & techniques covered here are only a
small subset of everything that is available in SAS 9. You should make sure
that you read the “What’s New” documentation for the version of SAS 9 that you
have. And don’t forget to always read the changes and enhancements for each new
service pack you get too.
ODS & Graph Features
Putting multiple graphs & tables on an HTML page
The guys at SAS have produced a wonderful new tagset called
the HTML Panel tagset. This will be available in SAS 9.2, but can be downloaded
and used now from this page http://support.sas.com/rnd/base/topics/odsmarkup/htmlpanel.html,
which also describes how to use it.
The tagset lets you do pretty much anything that you can do
with the normal ODS HTML destination, except you can break your page up into
rows and columns. So you could have 2 graphs at the top, followed by a table,
then perhaps 3 columns with graphs in each, etc. Just use your imagination.
The following code gives you a bit of an idea what can be
done with this tagset. It starts with 4 columns of bar charts, over 3 rows.
Then it has a report. And finally 5 columns of pie charts over 2 rows.
Note: before
you can use this tagset you need to download it and run the proc template code
in SAS to define it.
Sample Program
%let
panelcolumns = 4;
%let
panelborder = 4;
ods
tagsets.htmlpanel file="C:\bypanel2.html"
gpath='c:\'
options(doc='help');
goptions
device=java xpixels=320
ypixels=240;
title1 'Product Reports' ;
footnote1
;
proc summary data=sashelp.shoes nway
;
class
region product ;
var
stores sales inventory returns ;
output
out=sum sum= mean= /autolabel autoname ;
run ;
proc gchart data=sum ;
by
region ;
vbar
product / sumvar=sales_sum pattid=midpoint discrete ;
run;
quit;
proc summary data=sashelp.shoes nway
;
class
region subsidiary ;
var
stores sales inventory returns ;
output
out=sum sum= mean= /autolabel autoname ;
run ;
%let
panelcolumns = 5;
%let
panelborder = 1;
ods
tagsets.htmlpanel ;
title 'Summary data' ;
proc print data=sum ;
run ;
title 'Subsidiary Reports' ;
%let
panelcolumns = 5;
%let
panelborder = 1;
ods
tagsets.htmlpanel ;
goptions
dev=java xpixels=160
ypixels=120;
proc gchart data=sum ;
by
region ;
pie
subsidiary / sumvar=sales_sum discrete ;
run;
quit;
ods
_all_ close;
Output
Screen Shot 1

Screen Shot 2

Area charts which can compare magnitudes of variables in
categories
The GAREABAR procedure in SAS/Graph lets you compare the
magnitudes of 2 variables for each category of data using exact and relative
magnitudes of values. It only works with ODS using the activex or actimgx
driver though.
The following example plots sales on the x-axis,
relative percent of number of salespersons on the y-axis, with a bar for
each site. Additionally each bar is sub-grouped by quarter.
SAS Log
goptions reset=all device=activex ;
ods html file='c:\test.html' ;
data totals;
input Site $ Quarter $ Sales Salespersons;
cards;
NY 1 4225.26 12
NY 2 4595.07 18
NY 3 5847.91 24
NY 4 23388.51 26
;
proc gareabar
data=totals;
hbar site*salespersons /sumvar=sales
subgroup=quarter
rstat=SUM
wstat=PCT;
run ; quit ;
ods html close;
Plot details of slices in a Pie Graph
In SAS 9 there is a new parameter in
PROC GCHART that can be used when making PIE charts. It allows you to produce
an inner pie overlay, showing major components that make up outer pie slices.
This can be useful to get even more information into your chart. See the
example below.
SAS Program
ods html file='c:\test.html' gpath='c:\' ;
goptions reset=all
device=png
xmax=20
ymax=12
/* make PNG bigger */
ftext='Arial'
htext=4pct /* use some nice looking text
*/;
data countries;
input country $ 1-14 region $16-26 Machinery;
cards;
Malaysia2
Malaysia4
Malaysia5
Santa
Bob
Cydonia Mars 1.1
Tims House Mars
1.0
Malaysia3
;
run;
proc gchart;
pie region / angle=320
slice=outside
percent=inside
value=none
sumvar=Machinery
detail_percent=best
detail=country
descending ;
run; quit;
ods html close ;

Generating graphs automatically for some procedures
There is a new feature available for some SAS/STAT procedures
in SAS 9 which will produce a graph automatically. One such procedure is PROC
LIFETEST. To get the graph you simply turn ODS GRAPHICS ON and then choose the
graph required using the plots=(variable) option on PROC LIFETEST.
Sample code
ods listing close ;
ods html file='lifetest.html' style=mystyle;
ods graphics on;
proc lifetest
data=sasuser.fitness;
time age;
survival
confband=all plots=(hwb);
run;
ods graphics off;
ods html close;
Graph produced

Using Java & ActiveX to generate static graphs
In SAS 9 there are 2 new graphic devices that can be used to
create graphs called actximg & javaimg. These produce very
good looking graphics but are not interactive graphics, as their siblings are (ActiveX
& Java). The files produced are actually in PNG format and by
default will be 640x480 pixels (VGA). Try them out and see how easy it is to
produce excellent looking output. The graph produced below was only 5.6kb in
size.
Sample code
goptions device=actximg
;
/*goptions device=javaimg ;*/
ods html body='c:\test.html'
gpath='c:\'
(url=none) ;
proc gchart
data=sashelp.shoes ;
vbar3d product / sumvar=sales ;
run ;
ods html close ;
Graph produced using
ActXimg

Make combined Bar chart and plot the easy way
In SAS 9 there is a new SAS/Graph procedure which can make a
combined vertical bar chart with a plot line on it. It is great for comparing
two exact and relative magnitudes of values. It only works with ODS using the activex
or actimgx driver though.
SAS Log
goptions reset=all device=activex ;
ods html file='c:\test.html' ;
proc gbarline
data=sashelp.prdsale;
bar product / sumvar=actual ;
plot predict ;
run; quit;
ods html close;
Screen Shot
Producing multi-column reports
From SAS 9 onwards there is a new ODS option called columns=
which
allows you to choose the number of columns to produce in your output. This
works for some destinations including PDF, RTF & PS.
The following example shows how this can be used to send
output to various destinations & select various numbers of columns by using
macro variables.
SAS Program
%let dest=rtf; * pdf, ps or rtf
;
%let cols=2 ;
ods &dest columns=&cols file="c:\test.&dest" ;
goptions rotate=landscape ;
proc print data=sashelp.shoes ;
var region
stores sales ;
run ;
ods &dest close ;
1st page of Output
|
Obs |
Region |
Stores |
Sales |
|
1 |
|
12 |
$29,761 |
|
2 |
|
4 |
$67,242 |
|
3 |
|
7 |
$76,793 |
|
4 |
|
10 |
$62,819 |
|
5 |
|
14 |
$68,641 |
|
6 |
|
4 |
$1,690 |
|
7 |
|
2 |
$51,541 |
|
8 |
|
12 |
$108,942 |
|
9 |
|
21 |
$21,297 |
|
10 |
|
4 |
$63,206 |
|
11 |
|
13 |
$123,743 |
|
12 |
|
25 |
$29,198 |
|
13 |
|
17 |
$64,891 |
|
14 |
|
9 |
$2,617 |
|
15 |
|
12 |
$90,648 |
|
16 |
|
20 |
$4,846 |
|
17 |
|
25 |
$360,209 |
|
18 |
|
5 |
$4,051 |
|
19 |
|
9 |
$10,532 |
|
20 |
|
9 |
$13,732 |
|
21 |
|
3 |
$2,259 |
|
22 |
|
14 |
$328,474 |
|
23 |
|
3 |
$14,095 |
|
24 |
|
14 |
$8,365 |
|
25 |
|
13 |
$17,337 |
|
26 |
|
12 |
$39,452 |
|
27 |
|
8 |
$5,172 |
|
28 |
|
4 |
$42,682 |
|
29 |
|
24 |
$19,282 |
|
30 |
|
1 |
$9,244 |
|
31 |
|
3 |
$18,053 |
|
32 |
|
18 |
$26,427 |
|
33 |
|
11 |
$43,452 |
|
34 |
|
7 |
$2,521 |
|
35 |
|
1 |
$19,582 |
|
Obs |
Region |
Stores |
Sales |
|
36 |
|
6 |
$48,031 |
|
37 |
|
16 |
$13,921 |
|
38 |
|
5 |
$57,691 |
|
39 |
|
10 |
$16,662 |
|
40 |
|
11 |
$52,807 |
|
41 |
|
10 |
$4,888 |
|
42 |
|
1 |
$17,919 |
|
43 |
|
3 |
$32,928 |
|
44 |
|
8 |
$6,081 |
|
45 |
|
3 |
$62,893 |
|
46 |
|
2 |
$29,582 |
|
47 |
|
9 |
$11,145 |
|
48 |
|
5 |
$19,146 |
|
49 |
|
2 |
$801 |
|
50 |
|
1 |
$8,467 |
|
51 |
|
25 |
$16,282 |
|
52 |
|
1 |
$8,587 |
|
53 |
|
19 |
$16,289 |
|
54 |
|
12 |
$34,955 |
|
55 |
|
10 |
$2,202 |
|
56 |
|
3 |
$28,515 |
|
57 |
|
1 |
$1,996 |
|
58 |
|
1 |
$3,033 |
|
59 |
|
1 |
$3,230 |
|
60 |
|
1 |
$3,019 |
|
61 |
|
1 |
$5,389 |
|
62 |
|
17 |
$60,712 |
|
63 |
|
1 |
$11,754 |
|
64 |
|
7 |
$116,333 |
|
65 |
|
3 |
$4,978 |
|
66 |
|
21 |
$149,013 |
|
67 |
|
1 |
$937 |
|
68 |
|
2 |
$20,448 |
|
69 |
|
7 |
$78,234 |
|
70 |
|
1 |
$1,155 |
Page x of y in RTF & PDF
In SAS 9 if you want to add page numbers to your RTF output
in the form of “page x of y” then you can use the in-line formatting by
specifying an escape character and {pageof} – which will generate RTF code to
display x of y on each page. {pageof} only works for the RTF
destination.
If you want to do this for the PDF or Printer
destination.then you need to use a slightly different technique. You can use
the in-line style directive {thispage} which will give the current page
number, and {lastpage} will give the last page number.
Sample code for RTF
ods escapechar = '\';
title 'This document will have
page x of y '
j=r 'Page \{pageof}'
;
ods rtf file='c:\test.rtf'
;
proc print data=sashelp.prdsale;
run;
ods rtf close;
Sample code for PDF
ods escapechar = '\';
title 'This document will have
page x of y '
j=r 'Page
\{thispage} of \{lastpage}' ;
ods pdf file='c:\test.pdf'
;
proc print data=sashelp.prdsale;
run;
ods pdf close;
Discovering ODS events, to help make tagsets
ODS is very flexible and provides PROC TEMPLATE which can be
used to create your own custom tagsets. Then using the MARKUP destination you
can use your tagset to create the required output. This is a hugely powerful
and flexible facility, but often baffles those trying to use it. One common
question is “what events should I define in my tagset?”. Well the developer
of the ODS tagset mechanism (Eric
Gebhart at SAS) has provided 2 tagsets that can be used to display the events
that occur when producing some ODS output.
EVENT_MAP
creates XML output that shows which events are being
triggered and which variables are used by an event to send output from a SAS
process to an output file. When you run a SAS process with EVENT_MAP, ODS
writes XML markup to an output file that shows all event names and variable
names as tags. The output helps you to create your own tagsets. e.g.
ods
markup file='test.xml'
tagset=event_map ;
proc print data=sashelp.class ; run
;
ods
_all_ close ;
dm "wbrowse 'test.xml'" ;
SHORT_MAP
creates a subset of the XML output that is created by
EVENT_MAP. e.g.
ods
markup file='test.xml'
tagset=short_map ;
proc print data=sashelp.class ; run
;
ods
_all_ close ;
dm "wbrowse 'test.xml'" ;
Contact Information
Your comments and questions are valued and encouraged. Contact the author at:
Wood Street Consultants
Ltd.
E-mail:
phil@woodstreet.org.uk
Web:
www.woodstreet.org.uk
SAS and all other SAS Institute Inc. product or service names are
registered trademarks or trademarks of SAS Institute Inc. in the
Other brand and product names are trademarks of their respective
companies.