Image483_fmt.png

Chapter 11 Output Delivery System

11.1 Using the OUTPUT Destination

11.1.1 Determining Object Names

11.1.2 Creating a Data Set

11.1.3 Using the MATCH_ALL Option

11.1.4 Using the PERSIST= Option

11.1.5 Using MATCH_ALL= with the PERSIST= Option

11.2 Writing Reports to Excel

11.2.1 EXCELXP Tagset Documentation and Options

11.2.2 Generating Multisheet Workbooks

11.2.3 Checking Out the Styles

11.3 Inline Formatting Using Escape Character Sequences

11.3.1 Page X of Y

11.3.2 Superscripts, Subscripts, and a Dagger

11.3.3 Changing Attributes

11.3.4 Using Sequence Codes to Control Indentations, Spacing, and Line Breaks

11.3.5 Issuing Raw RTF Specific Commands

11.4 Creating Hyperlinks

11.4.1 Using Style Overrides to Create Links

11.4.2 Using the LINK= TITLE Statement Option

11.4.3 Linking Graphics Elements

11.4.4 Creating Internal Links

11.5 Traffic Lighting

11.5.1 User-Defined Format

11.5.2 PROC TABULATE

11.5.3 PROC REPORT

11.5.4 Traffic Lighting with PROC PRINT

11.6 The ODS LAYOUT Statement

11.7 A Few Other Useful ODS Tidbits

11.7.1 Using the ASIS Style Attribute

11.7.2 ODS RESULTS Statement

The Output Delivery System, ODS, has so many intricacies that only a very few can be mentioned here. Indeed, more than one book has been written where ODS is either the primary topic or an important secondary topic. This chapter is aimed at highlighting a few useful topics.

SEE ALSO

The classic go-to document for ODS is Output Delivery System: The Basics and Beyond by Haworth, Zender and Burlew (2009). Find tip sheets for ODS at http://support.sas.com/rnd/base/ods/scratch/ods-tips.pdf

Lund (2006) covers a great many of the topics found in this chapter and has a very nice summary of ODS attributes and the destinations to which they apply.

11.1 Using the OUTPUT Destination

While most procedures have one or more options that can be used to route procedural results to data sets, not all values can be captured this way. The OUTPUT destination allows us to capture procedure results as data. This destination is especially useful when there is no option available to write a specific statistic to a data set, or when a procedure does not have the capability of generating output data sets.

The output from each procedure is organized into one or more objects. These objects have a series of properties including a name and a label. This name (or the label) can be used on the ODS OUTPUT statement as an option to create an output data set.

The examples in this section use PROC UNIVARIATE; however, most of the discussion applies to most other procedures as well.

11.1.1 Determining Object Names

In its simplest, the UNIVARIATE procedure creates five output objects, and we will need at least the object name to make use of the OUTPUT destination.

ods trace on; Callout 1
proc univariate data=advrpt.demog;
   var ht wt;
   run;
ods trace off; Callout 2

The labels of the five basic objects produced by PROC UNIVARIATE for each of the analysis variables can be seen in the RESULTS window. If you right click on the label you can examine the objects attributes, including the name.

Since the ODS TRACE statement with the ON option Callout 1 was used, these attributes will also be displayed in the LOG. The portion of the LOG shown to the right shows the attributes of two of the five objects. The TRACE statement is turned off with the OFF option Callout 2.

image shown here

portions of the LOG not shown.
Output Added:
-------------
Name:       Quantiles
Label:      Quantiles
Template:   base.univariate.Quantiles
Path:       Univariate.wt.Quantiles
-------------

					
Output Added:
-------------
Name:       ExtremeObs
Label:      Extreme Observations
Template:   base.univariate.ExtObs
Path:       Univariate.wt.ExtremeObs

11.1.2 Creating a Data Set

The name of the output object (or its label) is used as an option on the ODS OUTPUT statement to name the data set that is to be created. In this example we want to collect information on the observations with the extreme values. By default PROC UNIVARIATE identifies the five observations containing the maximums and minimums of the analysis variables.

ods listing close; Callout 1
title1 '11.1.2a Naming the OUTPUT Data Set';
ods output extremeobs=maxmin; Callout 2
proc univariate data=advrpt.demog;
   id lname fname; Callout 3
   var ht wt; Callout 4
   run;
ods listing; Callout 5
proc print data=maxmin;
   run;

Callout 1 In this case we only want PROC UNIVARIATE to create a data set (no printed output), so all destinations other than OUTPUT are closed. We could not just use the NOPRINT option, because it also blocks the ability of the OUTPUT destination to create a data set.

Callout 2 The name of one or more output objects (EXTREMEOBS) is used as an option on the ODS OUTPUT statement to name the data set that is to be created (WORK.MAXMIN).

Callout 3 The ID statement names one or more variables useful in identifying the selected observations.

Callout 4 Two analysis variables are specified.

Callout 5 The LISTING destination has been turned back on and PROC PRINT is used to show the data set built by the OUTPUT destination.

The LISTING output of the resulting data set (WORK.MAXMIN) shows the observation number and identification variables for the five maximum and minimum values for each analysis variable.

11.1.2a Naming the OUTPUT Data Set
      Var          lname_     fname_                   lname_    fname_   High                                                      
Obs   Name   Low   Low         Low     LowObs   High   High       High     Obs                                                      
                                                                                
  1    ht     62   Moon       Rachel       51     74   Lawless   Henry      38                           
  2    ht     62   Karson     Shawn        36     74   Mercy     Ronald     50                           
  3    ht     62   Cranston   Rhonda       18     74   Nabers    David      53                           
  4    ht     62   Carlile    Patsy        11     74   Panda     Merv       56                           
  5    ht     63   Temple     Linda        72     74   Taber     Lee        70                           
  6    wt     98   Karson     Shawn        36    215   Mann      Steven     43                           
  7    wt     98   Carlile    Patsy        11    215   Marks     Gerald     44                           
  8    wt    105   Stubs      Mark         69    215   Rose      Mary       63                           
  9    wt    105   Maxwell    Linda        49    240   Antler    Peter       4                           
 10    wt    105   Leader     Zac          39    240   King      Doug       37                           

Using CLASS and BY Variables

When CLASS or BY variables are added to the PROC step, the resulting data set is expanded to include them.

title1 '11.1.2b CLASS Variable Present';
ods output extremeobs=maxclass(keep=sex varname high Callout 6
                                    lname_high fname_high);
ods listing close;
proc univariate data=advrpt.demog;
   class sex; Callout 7
   id lname fname;
   var ht wt;
   run;

Callout 6 Data set options (see Section 2.1) can be included when naming the new data set.

Callout 7 When one or more classification variables are used, they are added to the new data set for each combination of levels. The BY statement yields a similar result; however, the order of both the observations and the variables will be different.

11.1.2b CLASS Variable Present
       Var                    lname_       fname_
Obs    Name    sex    High    High          High
                Callout 7
  1     ht      F       68    East         Jody
  2     ht      F       68    Rose         Mary
  3     ht      F       68    Wills        Norma
  4     ht      F       72    Adamson      Joan
  5     ht      F       72    Olsen        June
  6     ht      M       74    Lawless      Henry
  7     ht      M       74    Mercy        Ronald
. . . .  portions of this listing are not shown . . . .

Using the Object’s Label

The object’s label can be used instead of the object name on the ODS OUTPUT statement. Here the example from 11.1.2a is repeated using the quoted label (extreme observations) Callout 8 instead of the object name.

ods output Callout 8'extreme observations'=extobs;

Driving an Automated Process

Any data set or even any information arranged in rows and columns can be used as the driving information for automating a process. The SAS macro language is especially powerful when it comes to creating applications and programs that rely on external information to make decisions.

In this example that external information will be a data set created through the use of ODS and the OUTPUT destination. The example process shown here, one that we would like to execute many times, is a simple PROC PRINT, but in reality it could be any number of DATA and PROC steps. In this case we want to execute the %PROCESS macro once for every level of a classification variable (in this example the classification variable must be character). The control will be accomplished using a WHERE clause Callout 1 that will be constructed in the controlling macro (%DOPROCESS) Callout 4.

%macro process(dsn=,whr=);
   proc print data=&dsn;
      where &whr; Callout 2
      run;
%mend process;

The controlling macro, %DOPROCESS, uses PROC FREQ with the OUTPUT destination Callout 2 to form a data set containing one level for each distinct value of the classification variable (&CVAR).

%macro doprocess(dsn=, cvar=);
ods output onewayfreqs=levels; Callout 2
proc freq data=&dsn;
   table &cvar;
   run;
data _null_;
   set levels; Callout 3
   whr = cats("&cvar='",&cvar,"'"); Callout 4
   call execute('%nrstr(%process(dsn='
               ||"&dsn"||',whr='
               ||whr||'))'), Callout 5
   run;
%mend doprocess;
%doprocess(dsn=advrpt.demog, cvar=sex) Callout 6

Callout 2 ODS OUTPUT and a PROC FREQ are used to create a data set (WORK.LEVELS) that will contain one row for each unique value of the classification variable (&CVAR).

Callout 3 The data set created by the OUTPUT destination is read as input for the DATA _NULL_ step.

Callout 4 The WHERE criteria is constructed and placed in the variable WHR, which will be added as text to the macro call Callout 5.

Callout 5 CALL EXECUTE is used to build a series of calls to the macro %PROCESS; one for each level of the classification variable.

Callout 6 The %DOPROCESS macro is called with the data set and classification variable of interest.

MORE INFORMATION

In this example an SQL step could have also been used to create the data set WORK.LEVELS, but this is not always the case. PROC SQL is used to create a distinct list of values in the second example in Section 11.2.2.

11.1.3 Using the MATCH_ALL Option

Obviously once the data set has been created, a variety of subsetting techniques can be used to break it up into distinct slices. If you know that the data set is to be broken up using BY/CLASS values, you can save the subsetting step(s) by using the MATCH_ALL option Callout 1. Notice the placement of the option, within parentheses following the object name.

ods output extremeobs(match_all Callout 1 )=matched;
proc sort data=advrpt.demog
          out=bysex;
   by sex;
   run;
proc univariate data=bysex;
   by sex;
   id lname fname;
   var ht wt;
   run;

In this step there are four combinations of SEX (M/F) and the analysis variables (HT/WT), and the MATCH_ALL option generates four data sets - one for each combination. The first is named WORK.MATCHED, the second WORK.MATCHED1, and so on. The listing for the first combination (WORK.MATCHED) is shown below. Notice that in this example a BY statement was used, rather than a CLASS statement as in the example in Section 11.1.2b. This allows you to observe the differences in the order of the variables and observations. Here the first of the data sets (WORK.MATCHED) is printed.

image shown here

11.1.3 Using MATCH_ALL
matched
          Var        lname_    fname_                lname_   fname_  High                           
Obs  sex  Name  Low  Low        Low    LowObs  High  High      High    Obs                           
 1    F    ht    62  Moon      Rachel      19   68   East     Jody       6                           
 2    F    ht    62  Karson    Shawn       12   68   Rose     Mary      22                           
 3    F    ht    62  Cranston  Rhonda       5   68   Wills    Norma     30                           
 4    F    ht    62  Carlile   Patsy        4   72   Adamson  Joan       2                           
 5    F    ht    63  Temple    Linda       28   72   Olsen    June      21                           

11.1.4 Using the PERSIST= Option

The PERSIST option is typically used to modify selection lists, and what we have essentially done in the ODS OUTPUT statement (Section 11.1.3) is specify a list of selected objects. The PERSIST= option determines how long the specified object should remain on the selection list. For the OUTPUT destination the list of selected objects is by default cleared (EXCLUDE ALL) at the step boundary.

Although the OUTPUT destination will by default generate data sets from a single PROC step, you may want to create a data set based on the results of two or more steps (generally of the same procedure). Rather than first creating the data sets individually and then later combining them in a secondary DATA step,
they can be combined
directly using the PERSIST= option Callout 1.

title1 '11.1.4 Using the Persist Option';
ods output extremeobs(persist=proc Callout 1)=pmatched;
ods listing close;
proc univariate data=advrpt.demog;
   class sex;
   id lname fname;
   var ht wt;
   run;
proc univariate data=advrpt.demog;
   class edu;
   id lname fname;
   var ht wt;
   run;
ods output close; Callout 2

Callout 1 Using PERSIST=PROC maintains the selection list past the step boundary. The data set remains open until the destination is closed Callout 2 or the list is otherwise cleared. This allows ODS to write the results of more than one procedure to the same data set (WORK.PMATCHED).

Callout 2 This ODS destination is closed. When the PERSIST= option is used it is important to close this destination. In this example you could have also used CLEAR instead of CLOSE; however, CLEAR merely resets the SELECT/EXCLUDE list to EXCLUDE=ALL.

The list of variables generated by the two PROC UNIVARIATE steps is almost the same. Since the classification variable differs, each step will contribute its classification variable as a column in the new data set (WORK.PMATCH). Effectively the data sets created by the two procedure steps individually have been concatenated. Adding the MATCH_ALL option would have resulted in separate data sets (see Section 11.1.5).

SEE ALSO

The PERSIST= option is discussed by Bryant, Muller, and Pass (2003).

11.1.5 Using MATCH_ALL= with the PERSIST= Option

When the MATCH_ALL= option and the PERSIST= option are used together, a series of related data sets with similar Program Data Vectors can be generated.

ods output extremeobs(match_all=series Callout 1
                      persist=proc Callout 2)=HT_WT Callout 3;
ods listing close;
proc univariate data=advrpt.demog;
   class sex;
   id lname fname;
   var ht wt;
   run;
proc univariate data=advrpt.demog;
   class edu;
   id lname fname;
   var ht wt;
   run;
ods output close;

In this example the MATCH_ALL= results in a series of data sets in the form of Callout 3 WORK.HT_WT, WORK.HT_WT1, WORK.HT_WT2, etc. Since we are using multiple procedures Callout 2 along with classification variables, the number of data sets may not be easily known. Callout 1 The list of the names of the data sets generated by the use of the MATCH_ALL=option can be stored in a macro variable (&SERIES) Callout 1.

For this example we could write this macro variable’s value to the LOG using the %PUT statement.

64   %put &series;
HT_WT HT_WT1 HT_WT2 HT_WT3 HT_WT4 HT_WT5 HT_WT6 HT_WT7 HT_WT8 HT_WT9 HT_WT10 HT_WT11 HT_WT12 HT_WT13 HT_WT14 HT_WT15 HT_WT16 HT_WT17 HT_WT18 HT_WT19

In earlier versions of SAS this list was often used with a SET statement to concatenate the data sets. This gives us some additional control. In the DATA step that concatenates these data sets an IF statement Callout 4 has been used to subset the data. A WHERE statement could not be used because the variable EDU is present only in those data sets generated by the second PROC UNIVARIATE step. The SET statement could also have been written without the macro variable by using a data set list abbreviation.

data HT_WT_all;
   set &series;
   if edu < '13'; Callout 4
   run;

When using the current versions of SAS, the MATCH_ALL= option is no longer necessary to produce a concatenated data set. In this example including the PERSIST= Callout 2 without the MATCH_ALL= Callout 1 (see Section 11.1.4), would result in a single data set (WORK.HT_WT) that included the output from both PROC UNIVARIATE steps.

set ht_wt:;

11.2 Writing Reports to Excel

There are several ways to write reports and procedure output directly to EXCEL tables. The results vary and method selection should depend on the desired result.

Destination

File

Type

File Characteristics

HTML

HTML

Uses the HTML4 tagset to generate an HTML 4.0 file. Not all style attributes are transferred to EXCEL.

HTML3

HTML

HTML 3.2 standard file. Was the only HTML destination under SAS 8. Attribute handling is different than the HTML destination under SAS®9.

MSOFFICE2k

HTML

(tagset) Supports importation of SAS/GRAPH images. Optimized for MSOffice 2k environment.

EXCELXP

XML

(tagset) Emphasis is on the data not the text. Supports writing to EXCEL Workbooks and multiple worksheets.

By far the most flexible approach and the only one that supports the XML standard is through the use of the EXCELXP tagset. This tagset is under constant development with new features being added on a regular basis. The latest version of this tagset along with a number of supporting papers and examples can be downloaded at http://go.sas.com/62454.003.


				
ods tagsets.excelxp Callout 1
           style=default
           path="&path
esults"
           body="E11_2.xls";
title1 '11.2 Using the EXCELXP Tagset';
title2 "Using the ExcelXP Tagset";
proc report data=advrpt.demog 
            nowd split='*';
portions of the PROC REPORT step not shown

Callout 1 EXCELXP is a tagset within the MARKUP destination. You may also address the tagset as an option on the ODS MARKUP statement Callout 2 .

 Callout 2 ods markup tagset=excelxp . . . 

The emphasis for this tagset is on the data and not necessarily on the text. Notice that, using the defaults, the two titles do not even appear in the Excel spreadsheet. Of course the titles can be included through the use of the embedded _titles='yes' option. This is just one of the many available options. To see the current list of available options use the DOC=’help’ option Callout 3, which writes a list of options to the LOG.

ODS tagsets.excelxp file="&path esults est.xml"

options(doc="help");

image shown here

SEE ALSO

The EXCELXP tagset is further discussed in (Andrews, 2008). Eric Gebhart (Gebhart, 2010) has written a number of papers on this tagset. Vince DelGobbo has written over a dozen papers on the EXCELXP tagset. An overall index to Vince’s papers can be found at http://www.sas.com/events/cm/867226/ExcelXPPaperIndex.pdf with a full list of his and other SAS author’s papers found at http://support.sas.com/rnd/papers/index.html.

11.2.1 EXCELXP Tagset Documentation and Options

The operation of the EXCELXP tagset is controlled through the use of options. These are implemented using the OPTIONS option with the options themselves enclosed in parentheses which follow the OPTIONS keyword. Here the DOC= option is used to write the tagset’s full documentation to the LOG. If you want to learn about recent changes to the tagset, the CHANGELOG option options(doc="changelog") will show you the timing of changes and summary of new features.

ODS tagsets.excelxp 
      path="&path
esults"
      body="E11_2_1.xls"
      options(doc="help");

SEE ALSO

The EXCELXP tagset is constantly being updated and refined. If you are using the version of the EXCELXP tagset that was shipped with SAS it is unlikely to be current. You can learn how to download and install the latest version of the EXCELXP tagset by reading SAS Note #32394 at http://support.sas.com/kb/32/394.html.

11.2.2 Generating Multisheet Workbooks

When writing a report or data set to Excel, it is not uncommon to need to break it up into portions that are written to individual sheets in the workbook. This can be accomplished in a couple of different ways. The primary difference between the two techniques shown here is whether you are sending a report or just the data to the spreadsheet.

When writing a report to Excel the EXCELXP tagset is the most flexible choice. This is demonstrated in this example with a PROC PRINT. This technique utilizes BY-group processing to break up the report.

%macro multisheet(dsn=,bylist=);
ods tagsets.excelxp Callout 1
           style=default
           path="&path
esults"
           body="E11_2_2a.xls"
           options(sheet_name='none' Callout 2
                   sheet_interval='bygroup' Callout 3
                   embedded_titles='no'), Callout 4
proc sort data=&dsn out=sorted;
   by &bylist;
proc print data=sorted;
   by &bylist; Callout 5
   run;
ods tagsets.excelxp close;
%mend multisheet;
%multisheet(dsn=advrpt.demog,bylist=race)

Callout 1 The EXCELXP tagset is selected for use.

Callout 2 Let the tagset determine the sheet name.

Callout 3 The SHEET_INTERVAL option determines how to break up the sheets.

Callout 4 Titles will not be included on the report. This is the default.

Callout 5 The BY line must be specified when using the SHEET_INTERVAL of ‘BYGROUP’ Callout 3.

For this macro call one sheet will be created for each level of RACE, including any missing values of RACE.

When breaking up a data set to multiple sheets we do not need to invoke the power of the EXCELXP tagset. Instead we can use PROC EXPORT. Here the EXPORT step is inside of a %DO loop that will execute once for each level of the selected classification variable.

%macro multisheet(dsn=,cvar=);
  %local varcnt type string i;
  proc sql noprint; Callout 6
    select distinct &cvar 
       into :idvar1 - :idvar&sysmaxlong
         from &dsn;
    %let varcnt = &sqlobs;
    quit;
data _null_; Callout 7
   if 0 then set &dsn;
   call symputx('type',vtype(&cvar),'l'),
   stop;
   run;
%do i = 1 %to &varcnt;
    %if &type=N %then %let string=&&idvar&i; Callout 8
    %else %let string="&&idvar&i";
    proc export 
           data=&dsn(where=(&cvar=&string)) Callout 9
           outfile="&path
esultsE11_2_2b.xls"
           dbms= excel
           replace;
       sheet = "&cvar._&&idvar&i"; Callout 10
       run;
 %end;
%mend multisheet;
%multisheet(dsn=advrpt.demog,cvar=race)

Callout 6 PROC SQL is used to create a series of macro variables to hold the distinct levels of the classification variable (&CVAR).

Callout 7 A DATA _NULL_ step is used to determine if the classification variable is numeric or character.

Callout 8 The WHERE criteria is established differentially for numeric and character variables.

Callout 9 The data set is subsetted using the WHERE criteria established at Callout 8.

Callout 10 The sheet is named using a combination of the variable’s name and its value.

SEE ALSO

The must-read paper on this topic is by Vince DelGobbo (2007). The PROC EXPORT example shown here was adapted to a sasCommunity.org article which shows a less generalized program to break up a data set into separate EXCEL sheets http://www.sascommunity.org/wiki/Automatically_Separating_Data_into_Excel_Sheets.

11.2.3 Checking Out the Styles

In addition to customized styles that you or your company may have created, SAS ships with over 40 predefined styles. With so many styles to choose from and since not all style attributes are carried over to the Excel spreadsheet when reports are written to Excel using the EXCELXP tagset, it becomes important to be able to visualize your report for each of the currently defined styles.

The %SHOWSTYLES macro uses the macro language to write a report to Excel once for each available style.

title1 '11.2.3 Showing Style in Excel';
%macro showstyles;
%local i stylecnt;
proc sql noprint;
   select scan(style,2,'.') Callout 1
      into: style1-:style&sysmaxlong
         from sashelp.vstyle;
   %let stylecnt = &sqlobs; Callout 2
   quit;
%do i = 1 %to &stylecnt; 
   ods markup tagset=excelxp
         path="&path
esults"
         file="&&style&i...xml" Callout 3
         style=&&style&I Callout 4
         options(sheet_name="&&style&i" Callout 5
         embedded_titles='yes'),
      title2 "Using the &&style&i Style"; 
      proc report data=sashelp.class nowd; Callout 6
         column name sex age height weight;
         define age    / analysis mean f=4.1;
         define height / analysis mean f=4.1;
         define weight / analysis mean f=5.1;
         rbreak after /summarize;
         run;
   ods markup close;
%end;
%mend showstyles;
ods listing close;
%showstyles Callout 7

Callout 1 An SQL step is used to create a macro variable for each of the unique style names.

Callout 2 The number of styles found is saved in &STYLECNT.

Callout 3 Inside the %DO loop the style name will be contained in the macro variable reference &&STYLE&I. The filename, therefore, contains the style name.

Callout 4 The style of interest is specified on the STYLE= option.

Callout 5 The sheet name will be the name of the style.

Callout 6 The report code will be exactly the same for each of the styles.

Callout 7 The %SHOWSTYLES macro is called.

11.3 Inline Formatting Using Escape Character Sequences

There are some types of formatting that is difficult or impossible to implement directly using ODS styles and options. However, through the use of an escape character it is possible to pass destination-specific commands directly to the destination that builds the output. The escape character alerts ODS that the associated formatting sequence of characters are not to be used directly by ODS, but rather are to be passed to the receiving destination.

The escape character should be one that you do not otherwise use in your SAS programs. Since I tend to not use the tilde as a negation mnemonic, it makes a good escape character. The escape character is designated using the ODS ESCAPECHAR option.

ods escapechar=’~’;

The escape character is used to note an escape sequence that may contain one or more destination commands or functions. The syntax varies by the kind of command.

Type

General Form

Used to

Section

Formatting Functions

~{function text}

Control pagination, superscripts, subscripts.

11.3.1

11.3.2

Style Modification

~S={attribute characteristics}

~{style elements and attributes}

Assign style attributes.

11.3.3

Sequence Codes

~code

Manipulate line breaks, wrapping, and indentations.

11.3.4

Raw Text Insertion

~R/destination “rawtext

~R “rawtext

Insert destination-specific codes.

11.3.5

SEE ALSO

Carpenter (2007a, Section 8.6) discusses inline formatting in the context of PROC REPORT steps.

Haworth, Zender, and Burlew (2009) discuss the use of the escape character and inline formatting sequences in a variety of usages.

Zender (2007) covers all the basics in this easy-to-read SAS Global Forum paper on inline formatting. If you want to know more, this should be the first paper that you read on this topic.

11.3.1 Page X of Y

A common requirement for multipage reports is to indicate the current page as well as the total number of pages, something like page 2 of 6. This can be accomplished in several ways, and the appropriate methodology depends on the destination, the placement of the text, and how the text is to be written out.

The RTF Destination - Using PAGEOF

When writing to the RTF destination, the pageof sequence can potentially be used to add page numbering. Designed to be used in a title or footnote, this formatting sequence can have unintended consequences when used elsewhere or if the BODYTITLE option is also used.

In this example a PROC REPORT step is executed with a BY statement causing a new page to be generated for each value of the BY variable.

ods escapechar='~'; Callout 1
options nobyline;
ods rtf file="&path
esultsE11_3_1a.rtf"
        style=rtf;
proc sort data=advrpt.demog
          out=demog;
   by symp;
   run;
proc report data=demog nowd split='*';
   title2 '#byvar1 #byval1'; Callout 2
   title3 '~{pageof}'; Callout 3
   by symp;
   column sex wt ht;
   define sex     / group 'Gender' order=data;
   define wt      / analysis mean format=6.1 ' ';
   define ht      / analysis mean format=6.1 ' ';
   compute after;
      line @3 'Page ~{pageof}'; Callout 4
   endcomp;
   run;
ods _all_ close;

Callout 1 The tilde is designated as the escape character.

Callout 2 Because the value of the BY variable has been placed in the title using the #BYVAL and #BYVAR options, the BYLINE is turned off. These options may not fully work if the TITLE statement containing the options is outside the PROC step.

Callout 3 The pageof formatting sequence is designated in the title. Notice that the sequence is enclosed in braces that follow the escape character. The page numbering appears correctly in the title line Callout 5.

Callout 4 For demonstration purposes the page numbering has also been requested through the LINE statement, which will write at the bottom of the report. Here the numbering is calculated incorrectly Callout 6. Remember that the pageof formatting sequence is designed to be used in the TITLE or FOOTNOTE statements and not in a LINE statement.

image shown here

When using RTF with MSWORD, the page numbers are sometimes not shown until the document is either printed or viewed in the print preview window.

MORE INFORMATION

The #BYVAL and #BYVAR title and footnote options are also used in Sections 7.4.3 and are discussed in Section 15.1.2.

SEE ALSO

Usage note 15727 discusses the use of the BODYTITLE option with the PAGEOF sequence.

The PDF and RTF Destinations - Using THISPAGE and LASTPAGE

The PAGEOF sequence is only available for the RTF destination; however, you can create even more flexible paging for both the RTF and PDF destinations by using the THISPAGE and LASTPAGE Callout 7 formatting sequences. Like the PAGEOF sequence, these are designed to be used in titles and footnotes, and unanticipated results can be expected when using the BODYTITLE option with the RTF destination.

ods pdf file="&path
esultsE11_3_1b.pdf"
        style=printer;
ods rtf file="&path
esultsE11_3_1b.rtf"
        style=rtf;
title1  '11.3.1b Using In-line Formatting';
title2 '#byvar1 #byval1';
title3 'THISPAGE and LASTPAGE';
title4 h=10pt 
       'This is Page ~{thispage} of a Total of ~{lastpage} Pages'; Callout 7
proc means data=demog n mean;
   by symp;
   class sex;
   var wt ht;
   run;
ods _all_ close;

image shown here

The behavior of the LASTPAGE sequence is similar to PAGEOF in the RTF destination. You may not be able to observe the total number of pages until you either do a print preview or scroll down a few pages in the table after it has been imported.

11.3.2 Superscripts, Subscripts, and a Dagger

In addition to paging information you can also draw attention to specific text by adding superscripts, subscripts, and a dagger symbol using inline formatting. Inline formatting functions include:

~{super 1} makes the 1 a superscript

~{sub 14} the number 14 becomes a subscript

~{dagger} the dagger symbol may be used instead of numbers.

title1  '11.3.2 In-line Formatting';
ods escapechar='~';
ods pdf file="&path
esultsE11_3_2.pdf"
        style=printer;
title2 'Superscripts and a Dagger ~{dagger}'; Callout 1
proc report data=advrpt.demog nowd split='*';
   column symp wt ht;
   define symp / group 'symptom' order=data;
   define wt   / analysis mean format=6.1 
                'Weight~{super 1}' Callout 2;
   define ht   / analysis mean format=6.1 
                'Height~{super 2}' Callout 2;
   compute after;
      line @1Callout 3 '~{super 1} Callout 2Pounds';
      line @1Callout 3 '~{super 2} Callout 2Inches';
      line @1Callout 3 '~{dagger} Callout 1 Using inline formatting';
   endcomp;
   run;
ods _all_ close;

Callout 1 The dagger symbol is placed in the title. The symbol itself does not have the same appearance in all destinations.

Callout 2 Superscripts are used to annotate the units of measure. In this PROC REPORT step they are applied in both the DEFINE statement and the LINE statement.

Callout 3 The column placement notation (@1) is not reliable in most destinations, especially when using proportional fonts. The @1 will reliably left justify the text; however, using something like @5 will not necessarily align text across rows.

image shown here

MORE INFORMATION

Aligning text across rows can be accomplished using inline formatting sequence codes; see Section 11.3.4. This same example demonstrates the use of the dagger as well.

11.3.3 Changing Attributes

Attributes associated with text can be changed using the inline style modifier. Most of the standard attributes that are set by the ODS style can be modified. The style modifier can be used virtually anywhere that you specify text. This includes not only titles and footnotes, but the labels of formatted values, and even the data itself. There are two general forms of the style modifier.

Prior to SAS 9.2 the only available form was:

~S={attribute=value}

Notice that an uppercase S= follows the escape character and precedes the curly braces. A typical use could be to change attributes of the text in a title.

title2 '~S={font_face="times new roman"} Callout 1 Initial'
       '~S={font_style=roman} Callout 2 Coded'
       '~S={} Callout 3 Symptoms';       

image shown here

Callout 1 The default title2 font is changed to Times New Roman.

Callout 2 Change the default font style from italics.

Callout 3 Changes are turned off and the defaults are restored.

Starting with SAS 9.2 a more flexible form of style modifier was introduced. The general form is:

~{style [element=attribute] text}

The style element and its attribute are enclosed within square brackets and together they precede the text to which the element/attribute pairs are to be applied. Notice that the braces enclose the text as well as the style elements.

The following TITLE statement generates the same title line as the TITLE statement of the previous example. Since modified attributes apply only to the text within the braces, the default attributes are applied to ‘Symptoms’.

title2 '~{style [font_face="times new roman"]Initial}' 
       '~{style [font_style=roman] Coded}'
       ' Symptoms';

image shown here

Either type of style modification sequence can be used outside of the TITLE and FOOTNOTE statements.

compute after;
 line @3 '~{style [font_weight=bold font_size=3] ~{super 1} Pounds}';
 line @3 '~{style [font_weight=light] ~{super 2}Inches}';
endcomp;

In fact they can be used most places where text is displayed. This includes data, labels, and formatted values. Here style modification sequences are applied in a LINE statement within a PROC REPORT compute block.

image shown here

SEE ALSO

Haworth, Zender and Burlew (2009, pg 268) creates several style modification sequences based on data values.

11.3.4 Using Sequence Codes to Control Indentations, Spacing, and Line Breaks

For some destinations, a series of sequence codes can be used with the escape character to control line breaks, indentations, and spacing. These codes may not work equally well for each of the primary destinations, and performance may be dependent on the version of SAS being used.

Code Sequence

What it does

Note

~m

Indentation location marker.

~-2n

Forces a line break (takes ~m into consideration).

~xn

Forces x line breaks (does not take ~m into consideration).

x= # of line feeds

~w

Suggested location for an optional line break.

~_

Creates a non-breaking space.

underscore

~xz

Inserts one of four error codes.

x=1, 2, 3, or 4


				
proc format;
   value $genttl  Callout 1      Callout 2
      'f','F'='Fe~mmale~-2nSubjects'
      'm','M'='Ma~mle~-2nSubjects';
   run;           Callout 1    Callout 2
title1 "Controlling Line Breaks";
proc report data=advrpt.demog nowd;
   columns sex ht wt;
   define sex   / group format=$genttl.
                  'Subject~w Gender'; Callout 3
   define ht    / analysis mean
                  format=5.2
                  'Height~{dagger}Callout 4';
   define wt    / analysis mean
                  format=6.2
                  'Weight~{dagger}';
   rbreak after / summarize;
   compute after;Callout 4        Callout 1
    line @1 '~{dagger} Eng~mlish Measures'
            '~-2nHeight(in.)~-2nWeight(lbs.)';
    line @1 'All su~mbjects were screened during '
            '~-2nthe intake session at visit one.';
   endcomp;    Callout 2
   run;

Callout 1 The ~m is used to mark the alignment location (indentation) for the line breaks specified with the ~-2n sequence.

Callout 2 Line breaks are forced using the ~-2n notation. Without forcing these breaks the width of the table would be driven by the LINE statement.

Callout 3 The ~w indicates an optional line break. This means that this will be the preferred location for a line break, if one is needed. In this table the text will break at the space with or without using the ~w.

Callout 4 The dagger symbol is added to associate the column label with the units footnote.

image shown here

11.3.5 Issuing Raw RTF Specific Commands

An RTF table or report is generated using a series of commands, control words, and field codes that are specific to the RTF destination (Section 15.3 goes into more detail on RTF code). Normally we do not need to know anything about those commands because they are written for us by ODS. However, when formatting sequences are not available for a specific task and you know the appropriate underlying command for the destination, you can pass the raw RTF destination-specific control code from SAS for execution at the destination.

You can issue these raw destination-specific commands using one of the following inline formatting functions. While the syntax used in SAS 9.1.3 will work in SAS 9.2, the newer preferred syntax is available starting in SAS 9.2. The escape character (here a tilde is used) must be declared using the ODS ESCAPECHAR option:

SAS 9.1.3 (and earlier)

~R/destination 'command' especially useful when multiple destinations are open ~R 'command'

SAS 9.2

~{raw 'command'}
~{dest[destination] 'command'}

In the following example, raw RTF commands are passed both through a format and in TITLE statements. The commands themselves are preceded by a back slash and followed by a space. Multiple raw commands can be chained together, and they are turned off by following the control code with a 0 (zero).

ods escapechar = '~';
proc format;
   value $gender
      'f','F'='~{raw  F0i emale}' Callout 1
      'm','M'='~{raw  M0i ale}' Callout 1;
   run;
title1  ~{raw '11.3.5 i0 Using ul RTF0ul0  Codes'}; Callout 2
title2 ~{raw 'i0 Italics off'};
proc report data=advrpt.demog nowd;
   columns sex ht wt;
   define sex   / group format=$gender.;
. . .  code not shown . . .

Callout 1 Bolding is turned on and off with the  and 0, while italics are turned on with i. Notice that the text in this format has control down to the letter (first letter bolded – remaining letters in italics).

Callout 2 The default for the RTF style turns italics on for titles. These have been turned off (except for the example number; 11.3.5).

image shown here

SEE ALSO

A few common RTF commands can be found in Haworth, Zender, and Burlew (2009, pg 128). The same section discusses an alternative approach using a style rather than inline formatting.

11.4 Creating Hyperlinks

Text, reports, graphs, and tables within electronic documents can automatically be connected by creating hyperlinks. SAS can create these links almost anywhere that text is displayed, as well as within graphic objects. Links can be established between portions of tables, graphs, other locations within a table, and between tables of different types. Within a table links can be established within data values, formats, titles, header text, and graphic symbols.

MORE INFORMATION

Links are created in a PROC PRINT example in Section 8.5.3.

SEE ALSO

A number of the following techniques are presented in PROC REPORT examples by Carpenter (2007b).

11.4.1 Using Style Overrides to Create Links

In the TABULATE, REPORT, and PRINT procedures the style overrides can be especially useful for creating links. The application of the style override option (STYLE=) is very similar in all three procedures; however, in PROC REPORT links can also be generated through the use of the CALL DEFINE routine.

In this example a report summarizes the data for each of the symptoms (SYMP). It is constructed so that clicking on the symptom number links to a report for that symptom.


				
%macro sympRPT;
title1  '11.4.1 Hyperlinks Using Style Overrides';
ods html file="&path
esultsE11_4_1.htm" Callout 1
         style=journal;
title2 'Symptoms';
proc report data=advrpt.demog nowd split='*';
   column symp wt ht;
   define symp / group 'Symptom' order=internal
                 missing;
   define wt   / analysis mean format=6.1 'Weight';
   define ht   / analysis mean format=6.1 'Height';
   compute symp;
      stag = 'E11_4_1_'||trim(left(symp))||'.htm'; Callout 2
      call define(_col_,'url',stag);
   endcomp;
   run;
ods _all_ close;
proc sql noprint;
   select distinct symp
      into: sym1-:sym999 Callout 3
         from advrpt.demog;
%do s=1 %to &sqlobs; Callout 4
ods html file="&path
esultsE11_4_1_&&sym&s...htm" 
         style=journal;
title2 "Symptom &&sym&s";
proc report data=advrpt.demog(where=(symp="&&sym&s"))Callout 5
            nowd split='*';
   column sex wt ht;
   define sex / group 'Sex' order=internal
                style(header)={url='e11_4_1.htm'}; Callout 6
   define wt   / analysis mean format=6.1 'Weight';
   define ht   / analysis mean format=6.1 'Height';
   run;
ods _all_ close;
%end;
%mend symprpt;
%symprpt

Callout 1 The primary HTML file is named and then created using PROC REPORT.

Callout 2 Each individual value of SYMP is associated with a file that will contain the summary for that symptom. The CALL DEFINE is used to associate the URL with the symptom.

Callout 3 An SQL step is used to assign the distinct values of SYMP to macro variables.

Callout 4 A macro %DO loop is used to cycle through the individual values of symptom (&&SYM&S).

Callout 5 The macro variable holding a specific symptom (&&SYM&S) is used to subset the data.

Callout 6 The style override option is used to assign the URL attribute to the header, which will now link back to the primary table.

image shown here

image shown here

MORE INFORMATION

Style overrides are introduced and discussed further in Sections 8.1.3 (TABULATE), 8.4.6 (REPORT), and 8.5.2 (PRINT). The CALL DEFINE routine is introduced in Section 8.4.7.

11.4.2 Using the LINK= TITLE Statement Option

In the TITLE and FOOTNOTE statements the LINK= option can be used to specify the file to which you want to link. The option can point to an internal anchor location, a local file, or may even contain a fully qualified path.

title1  '11.4.2 LINK= Option';
ods pdf file="&path
esultsE11_4_2.pdf" 
        style=journal;
title2 'Patient List Report';
title3 link='E11_4_1.htm' Callout 1      
       'Symptom Report';
proc print data=advrpt.demog;
   var lname fname sex dob symp;
   run;
ods _all_ close;

In this example the LINK= option Callout 1 is used to point back to the primary file created in Section 11.4.1.

image shown here

MORE INFORMATION

Other TITLE and FOOTNOTE statement options are described in Section 9.1.

11.4.3 Linking Graphics Elements

Most graphics elements can be created so that the viewer can click on them and then ‘drill down’ to another graph or report. Linkable graphic elements include, but are not limited to, histogram bars, scatter plot lines and symbols, maps, pie slices, and legend elements. Linkable elements can be enabled through the annotate facility as well as the techniques shown here.

While reports can be linked among the three primary destinations (MARKUP, PDF, RTF), linking from a graphics element requires a file designed for web viewing, such as GIF or PNG, with a markup overlay, such as HTML. This necessarily means that these techniques will not work for the LISTING destination.

The key is the generation of a character variable that contains the name of the file to which the element is to link. The following program creates a vertical histogram. Clicking on any one of the bars will display a report for the study participants with the selected number of years of education.

filename e1143 "&path
esultse11_4_3.png"; Callout 1
* Initialize graphics options;
goptions reset=all border 
         ftext=swiss 
         htext=1;
goptions device=png
         gsfname=E1143; Callout 1
data demog;
   set advrpt.demog(keep=edu wt);
   drilledu = catt('href=E11_4_3.pdf#_',
                   left(put(edu,2.))); Callout 2
   run;
                                     . . . . code not shown . . . .
* Create a chart that links to the summary report;
ods html path="&path
esults" (url=none) Callout 3
         body='E11_4_3.html';
PROC GCHART DATA=demog;
   VBAR edu / type=mean sumvar=wt
              discrete
              patternid=midpoint
              html=drilledu Callout 4
              raxis=axis1
              ;
   run;
   quit;
ods html close;

Callout 1 A PNG histogram will be created by PROC GCHART. By itself this file will not contain linkable elements.

Callout 2 The variable DRILLEDU contains the name of the file to which we will be linking. In this example all the reports are in a single file with internal anchor point labels Callout 8, therefore, the paths are all relative to each other. This variable could contain a fully qualified path.

Callout 3 Create the overlay file that contains the linkable elements that are associated with the
graph Callout 1.

Callout 4 The variable that contains the ‘link to’ filename Callout 2 is identified using the HTML option. The HTML_LEGEND option can be used when elements of the legend are to be made linkable.

The bars of the histogram will link to a series of reports, one for each vertical bar (value of EDU).

%macro BldRpt;
ods pdf file="&path
esultse11_4_3.pdf" Callout 5
        style=journal;
proc sql noprint; Callout 6
   select distinct edu
      into :edu1 - :edu99
         from advrpt.demog(keep=edu);
   %let educnt=&sqlobs;
   quit;
%do i = 1 %to &educnt; Callout 7
   ods pdf anchor="_&&edu&i"; Callout 8
   ods proclabel 'Symptom Summary'; Callout 9
   title3 "&&edu&i Years of Education";
   proc report data=advrpt.demog
                     (where=(edu=&&edu&i Callout 7)) 
               contents="_&&edu&i Years" Callout 10
               nowd;
      columns symp sex,wt;
      define symp / group;
      define sex  / across 'Gender';
      define wt   / analysis mean;
      run;
%end;
ods pdf close;
%mend bldrpt;
%bldrpt

Callout 5 The individual reports, to which we are linking from the histogram, are to be stored in this one PDF file.

Callout 6 The individual values of EDU are determined and stored in a list of macro variables using an SQL step.

Callout 7 A macro loop creates a series of reports – one for each value of EDU.

Callout 8 The drill down variable Callout 2 contains an anchor label reference within the PDF file. This label is created using the ANCHOR= option. The ANCHOR points are coordinated by using the macro variable reference &&EDU&I.

Callout 9 The ODS PROCLABEL statement is used to replace the procedure name in the PDF bookmarks with user-specified text.

Callout 10 The PDF Bookmark value is changed using the CONTENTS= option.

Clicking on the vertical bar associated with subjects with 12 years of education (second from left), opens the indicated PDF file at the appropriate anchor point.

image shown here image shown here image shown here

MORE INFORMATION

Internal links are discussed further in Section 11.4.4.

11.4.4 Creating Internal Links

While hyperlinks will usually point to the beginning of a file, it is not unusual for the link to point to a location within a file. This can be a location within a file other than the one being viewed or to another location within the same file. This is known as an internal link. In the example in Section 11.4.3 (see Callout 2) one of the links formed is a internal link.

Internal links are designated using a pound or hash sign (#). A pointer to an internal location within a file in the local directory might be named: E11_4_3.pdf#_15. The internal location is marked using the ANCHOR= option.

ods pdf anchor=_15;

In the following example a PDF document is created that contains the output from a PROC TABULATE and two PRINT procedure steps. The three reports are linked using internal locations.


				
                                . . . .  code not shown . . . .
 proc format;
   value $genlnk Callout 1 
      'M' = '#Males' 
      'F' = '#Females';
   run;
ods pdf anchor='Master'; 
ods proclabel='Overall'; 
proc tabulate data=tabdat.clinics;
   class sex ;
   classlev sex/ style={url=$genlnk. Callout 2
                        foreground=blue};
   var wt;
   table sex=' ', 
         wt*(n median min max)
         / box='Gender';
   run;
ods pdf anchor='Males'; Callout 3
ods proclabel='Males'; Callout 4
title2 link='#Master' Callout 5□'Return to Master';
title3 c=blue 'Males';
proc print data=tabdat.clinics;
   where sex='M'; Callout 6
   var lname fname ht wt;
   run;
. . . .  code not shown . . . .

				

Callout 1 A format is being used to assign the link location. The pound sign (#) identifies the link location as internal to the current file. Internal locations are specified with the ANCHOR= option Callout 3.

Callout 2 The name of the file or, in this case, the internal location to which we will link is assigned using the URL attribute. Since this STYLE override option is on the CLASSLEV statement, the levels of this classification variable will form the links.

Callout 3 The ANCHOR= option marks an internal location in the current document to which we can link.

image shown here

image shown here

image shown here

Callout 4 The ODS PROCLABEL statement changes how the results of this procedure are labeled in the PDF bookmarks.

Callout 5 The LINK= option can be used to create links in titles and footnotes. Notice the use of the # sign to designate the internal link

Callout 6 A WHERE statement is used to create the table for the males.

CAVEAT

When using SAS 9.2 under Windows, internal link locations and pointers for PDF documents should all be designated in lowercase. In SAS 9.1.3 mixed case is acceptable. This behavior may change in future releases of SAS. The problem stems from the conversion of all the anchor locations to lowercase when the document is rendered.

11.5 Traffic Lighting

Traffic lighting is a technique that allows the programmer to automatically change attributes of a report based on the values that are presented. Traditionally the background color is changed to red/yellow/green – hence the name. However any of the attributes can be changed; and most often a style override is used to change the attribute value. The key to the process is a user-defined format that is used to map the display value to the attribute that is to be changed.

MORE INFORMATION

Style overrides are introduced and discussed further in Sections 8.1.3 (TABULATE), 8.4.6 (REPORT), and 8.5.2 (PRINT). The CALL DEFINE routine is introduced in Section 8.4.7.

11.5.1 User-Defined Format

A user-defined format is used to associate an ODS attribute value with the values that are to be displayed in the table. Once established the format can be used by the TABULATE, REPORT, or PRINT procedures.

Although traditionally traffic lighting techniques are used to change colors, the extension of the concept allows us to change multiple attributes, including cell attributes such as links, font, font size, and bolding.

The VALUE or INVALUE statement is specified as always, however, the format’s label (text to the right of the equal sign) is the attribute value. The format is then used along with the attribute to which it is to be applied. Generally the association will be created using a STYLE override option and takes the form of attribute=format.

proc format;
   value $serious_f
      'YES','yes' = 'white';
   value $serious_b
      'YES','yes' = 'red';
   value $severity_f
      '3' = 'black'
      '4','5'= 'white';
   value $severity_b
      '3' = 'yellow'
      '4','5'= 'red';
   run;

11.5.2 PROC TABULATE

Although when using PROC TABULATE the STYLE override options can be applied to all aspects of the table, for traffic lighting we will generally want to highlight values of statistics or values derived from the data. To do this the STYLE override option will be nested under the statistic to which it is to be applied.

In the protocol for this study the subject’s initial weight should be between 100 and 235 pounds. This table highlights those clinics that have enrolled subjects that are out of compliance.

proc format;
   value MaxWT_f Callout 1
      235-high  = 'white'; Callout 2
   value MaxWT_b Callout 3
      235-high  = 'red'; Callout 4
   value MinWT_f
      low-<100  = 'white';
   value MinWT_b
      low-<100  = 'red';
   run;
title1 '11.5.2 Traffic Lighting: TABULATE';
title2 'Weight Compliance';
ods listing close;
ods pdf file="&path
esultse11_5_2.pdf"
        style=journal;
proc tabulate data=advrpt.demog
              (where=(clinnum in:('05','06')));
   class clinnum;
   var wt;
   table clinnum,
         wt*(min*{style={background=minwt_b.
                         foreground=minwt_f.}} 
             max*{style={background=maxwt_b. Callout 2
                         foreground=maxwt_f. Callout 1}});
   run;
ods pdf close;

Callout 1 The MAXWT_F. format will be used to alter the color of the text (foreground) Callout 2 for the maximum weights. The color of the background (red Callout 4)is altered by the MAXWT_B. Callout 3 format.

image shown here

The resulting table shows that at least two patients have been enrolled that do not meet the weight criteria. You will generally not be pleased with dark text on a dark background, which is why the foreground color was changed to white, when the background color was to be changed to red.

SEE ALSO

Carpenter (2010a) has a PROC TABULATE example of traffic lighting using the STYLE override option.

11.5.3 PROC REPORT

When using PROC REPORT the style override option can be applied in two ways. First, statement options such as the ones used in the example in Section 11.5.2 are applied directly. Second, in PROC REPORT the CALL DEFINE routine allows us to conditionally apply style overrides.

The examples in this section make use of the formats established in Section 11.5.1. In this report we would like to highlight adverse events which are either serious (SER=’YES’) or have a severity level which is greater than 3.

proc report data=advrpt.ae(where=(sev>'1')) nofs;
   column subject aestdt ser sev aedesc;
   define subject / order;
   define aedesc / order;
   define aestdt / display;
   define ser / display
                style(column) ={background=$serious_b. Callout 1
                                foreground=$serious_f.};
   define sev / display
                style(column) ={background=$severity_b. Callout 2
                                foreground=$severity_f.};
   run;

Formats for the foreground and background colors are applied to the display of the values of the seriousness (SER Callout 1) and severity (SEV Callout 2) of the event.

In the figure for example 11.5.3a (to the left), the severity codes 3 and greater are highlighted regardless of the seriousness of the event. These two formats are independent of each other and both are applied. Notice that subject 201 has two events highlighted (SEV>2), however, neither of the events is rated as serious (SER=NO).

image shown here

Because the CALL DEFINE is executable we can use IF-THEN/ELSE processing to conditionally assign a format. In this next example the traffic lighting style override for the severity is moved to a CALL DEFINE and is only applied for serious events (SER=YES). Callout 3 The CALL DEFINE results are applied to the current column Callout 4 which is SEV since we are executing the SEV compute block. The style override is selected Callout 5 and the style attributes that are to be applied are the same ones as were applied in the previous example Callout 2.

A portion of the PROC REPORT step is shown here.

   define ser / display
                style(column) ={background=$serious_b. Callout 1
                                foreground=$serious_f.};
   define sev / display;
   compute sev;
      if ser='YES' then Callout 3
        call define(_col_, Callout 4
                    'style', Callout 5
                    'style ={background=$severity_b. Callout 2
                             foreground=$severity_f.}'),
   endcomp;

Callout 3 The format for the severity has only been applied when the event is serious (SER=’YES’).

image shown here

SEE ALSO

The use of traffic lighting with PROC REPORT is covered in detail in Carpenter (2006b).

11.5.4 Traffic Lighting with PROC PRINT

Traffic lighting with PROC PRINT, like with PROC TABULATE and PROC REPORT (see Sections 11.5.2 and 11.5.3), is applied using the style override option. As was discussed in Section 8.5.2, which introduced the style override option for the PRINT procedure, the option can be applied on the VAR statement. The following example utilizes the formats created in Section 11.5.1 and the output mimics the first output generated by the REPORT procedure in Section 11.5.3.

ods pdf style=journal file="&path esultsE11_5_4a.pdf";

proc print data=advrpt.ae(where=(sev>'1'));

by subject;

id subject;

var aestdt ;

var ser / style(column)={background=$serious_b.

foreground=$serious_f.};

var sev / style(column)={background=$severity_b.

foreground=$severity_f.};

run;

ods pdf close;

Notice that the style override option is applied as an option on the VAR statement Callout 1 Callout 2. By splitting the VAR statement into two statements you can apply the traffic lighting formats differentially.

Like the figure in Section 11.5.3a this table applies the formats on the two variables independently. In PROC REPORT we were able to use the CALL DEFINE routine to conditionally apply the format for severity. In PROC PRINT the CALL DEFINE routine is not available and formats cannot be conditionally assigned.

image shown here

SEE ALSO

Carpenter (2006b) discusses traffic lighting in detail for the PROC REPORT step.

11.6 The ODS LAYOUT Statement

The ODS LAYOUT statement, which is available but was not yet production for SAS 9.2, can be used to place the results of multiple procedures, including graphics, on one page. The page is defined in terms of regions with a given procedure’s output being placed into a specific region. The user gets to define the number, size, and placement of the regions.

There are two basic types of layouts ABSOLUTE and GRIDDED. Absolute layouts, shown below, have fixed region sizes, while gridded layouts can be more dynamically allocated.

The ability to define and use the output regions is made available by turning on LAYOUT with the START option on the ODS LAYOUT statement. The general form of a program that utilizes LAYOUT will be something like the following:

ods layout start;
	ods region . . . 
	proc . . . .
	ods region . . . 
	proc . . . .
ods layout end;

Layout is turned on with the START option and off with the END option. Between the start and end will be one or more region definition followed by the procedure that will write to that region. Regions are rectangular and within the layout page regions are defined with the ODS REGION statement.

The primary options are:

  • X= horizontal position of the upper-left corner (measured from the left).
  • Y= vertical position of the upper-left corner (measured from the top).
  • width= width of the region.
  • height= height of the region.

You get to select the size of the region; however, you do need to be careful. If the region is too small this warning may appear in the LOG when using layout.

WARNING: THE ABSOLUTE REGION WAS TOO SMALL TO ACCOMMODATE THE TEXT SUPPLIED. OUTPUT WAS LOST.

The layout to the left establishes three regions. One for a title written by the TEXT= option, and two for side-by-side PROC REPORT tables.

%let text1 = ~S={font_face=arial  Callout 1 
font_weight=bold}11.6 Using ODS LAYOUT~S={font_face=arial}~nMean Weight and Height;
%let text2 = ~nfor Symptom and Years of Education;
title1;
ods pdf file="&path
esultsE11_6.pdf" Callout 2
        style=journal
        startpage=never; Callout 3
ods escapechar='~';

ods layout start width=7in height=10in; Callout 4

ods region x=1in y=1in width=7in height=.5in; Callout 5
ods pdf text="&text1&text2"; Callout 6
ods region x=0.5in y=1.5in width=7in height=4in; Callout 7
proc report data=advrpt.demog nowd;
                          . . . . REPORT code not shown . . . .
ods region x=1.5in y=1.5in width=3in height=4in; Callout 8
proc report data=advrpt.demog nowd; 
                          . . . . REPORT code not shown . . . .
ods _all_ close; Callout 9
ods layout end; Callout 10

Callout 1 The title for the page is saved in macro variables for use with the ODS PDF TEXT= option Callout 6. Inline formatting sequences (~n, ~S) are described in Section 11.3.

Callout 2 The PDF destination is opened.

Callout 3 Restrain PDF from starting a new page when going to a new procedure.

Callout 4 Open the layout space with an overall size definition.

Callout 5 Define the first region, which will hold the title text stored in the macro variables &TEXT1 and &TEXT2.

Callout 6 The text is written to the first region.

Callout 7 and Callout 8 The regions used by the two PROC REPORT steps are defined.

Callout 9 The PDF destination is closed. Actually here all destinations are closed.

Callout 10 The ODS LAYOUT section is closed.

image shown here

SEE ALSO

Rob Nelson (2010) creates a similar, but more complex layout. Along with a number of other ODS options, Dan O’Conner and Scott Huntley (2009) discuss both absolute and gridded layout options in detail. Chen (2005) introduces gridded layout.

11.7 A Few Other Useful ODS Tidbits

There are just way too many options and statements to fully describe them here. However there are a couple of which you should be at least aware.

11.7.1 Using the ASIS Style Attribute

The HTML destination removes spacing to give a ‘better’ display. When you want to preserve spacing surrounding a value, the ASIS option can prevent this behavior.

proc print data=advrpt.demog(obs=5);
   id lname;
   var fname ht wt;
   format wt 8.1;
run;

Although the format used with WT has a width of 8, the space surrounding the numbers only reflects the cell margins. We can preserve that space by using the ASIS style attribute; however, this attribute may also affect the bottom margin attribute.

The VAR statement has been broken into two statements so that we can associate STYLE override options with the variable WT. The header as also been centered.

   var fname ht; 
   var wt /style(data)={asis=yes}
           style(header)={just=c};

image shown here

Notice that the ASIS attribute has also increased the bottom margin of the cell.

image shown here

11.7.2 ODS RESULTS Statement

When we create RTF files under some combinations of operating systems and versions of Microsoft Office, a prompt is issued when the SAS viewer attempts to open the new RTF file. This can be especially troublesome when the files are generated as a part of an automated system or application.

One solution is to turn off the automatic viewing of the results. In the interactive environment this can be done manually by changing the preference settings. While running the SAS Display Manager go to:

Tools Options Preferences Results

Uncheck the “View results as they are generated” box.

The automatic viewing of results can also be controlled through the use of the ODS RESULTS statement. To override the preference that is selected through the Preferences Dialogue Box, you may use either:

ods results on;   Turn on automatic review of the results (typically the default).

ods results off;    Turn off automatic review of the results.

SEE ALSO

Alternative approaches and a deeper statement of the problem were discussed in the SAS Forum thread http://communities.sas.com/message/42066#42066.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset