To my mind, the ODS ESCAPECHAR is one of the most useful, but also most often misused statements in the ODS. As I have mentioned elsewhere, SAS Institute need to take most of the responsibilty for this: mention of the ODS ESCAPECHAR is entirely missing from the online documentation, and the examples that you can find on the web almost always the backslash as the ESCAPECHAR; a wonderfully inappropriate choice.
In a nutshell, using the ESCAPECHAR tells the ODS that what follows is a directive (usually relating to formatting and layout) rather than text that should appear in the destination. ESCAPECHAR differs from the PROTECTSPECIALCHARS style attribute in that it works across destinations, whereas using the PROTECTSPECIALCHARS style attribute almost always requires different choices for different destinations.
As a simple introductory example, suppose you want to print "y = ax2 + bx + c is a quadratic equation" in an HTML file, an RTF file and a PDF file. ODS ESCAPECHAR makes this as easy as pie.
DATA Quadratic;
LENGTH Text $ 40;
Text = "y = ax^{super 2} + bx + c is a quadratic equation";
OUTPUT;
RUN;
ODS ESCAPECHAR="^";
ODS RTF FILE="tut0002_1.rtf";
ODS PDF FILE="tut0002_1.pdf";
ODS HTML FILE="tut0002_1.htm";
PROC PRINT DATA=Quadratic;
RUN;
ODS PDF CLOSE;
ODS RTF CLOSE;
ODS HTML CLOSE;
In this example, we specify ODS ESCAPECHAR but don't need to mention the PROTECTSPECIALCHARS style attribute.
Notice that the superscript is correctly rendered in all the destinations except the listing destination. This is because the listing destination doesn't support this type of text effect.
The same effect can be achieved using the PROTECTSPECIALCHARS option, but since each destination has a different underlying control language, different commands are required. For example, here's the code to create an RTF file with a superscript. Look at the PDF file to see what happens when you accidentally mix up the command langauge for one destination with output to another.
DATA Quadratic;
LENGTH Text $ 40;
Text = "y = ax{\super 2} + bx + c is a quadratic equation";
OUTPUT;
RUN;
ODS RTF FILE="tut0002_2.rtf";
ODS PDF FILE="tut0002_2.pdf";
ODS LISTING CLOSE;
PROC PRINT DATA=Quadratic STYLE(DATA)=[PROTECTSPECIALCHARS=OFF];
RUN;
ODS PDF CLOSE;
ODS RTF CLOSE;
ODS LISTING
These examples illustrate one of the problems caused by using the backslash as the ESCAPECHAR. If we had, we'd have said
Text = "y = ax\{super 2} + bx + c is a quadratic equation";
in the first example and
Text = "y = ax{\super 2} + bx + c is a quadratic equation";
in the second. They're rather too similar for my liking, especially given the difference in their results.
This is only one of the effects that can be achieved using the ESCAPECHAR. Other inline formatting commands are:
Command | Version1 |
Description |
{super <text>} | 8 |
Renders <text> as a superscript |
{sub <text>} | 8 |
Renders <text> as a subscript |
{dagger} | 8 |
Prints † |
S={<attribute definitions>} | 8 |
Allows on-the-fly changes to style attributes. See below for more details. |
{thispage} | 9 |
The current page. See note 2 below. |
{numpages} | 9 |
The number of pages in the document. See note 2 below. |
{pageof} | 9 |
The same as ^{thispage} of ^{numpages}. See note 2 below. |
1: The version of SAS in which the facility was first available.
2: RTF files only. The page numbers are added as document fields. This means that if the RTF file is to be included as a sub document of another, master, document, page numbering may still go awry. See my essay on Pagination and the Output Delivery System for more details. The SRS Paginator system corrects this problem.
NB ESCAPECHAR sequences are case sensitive.
NB There are a few other ESCAPECHAR sequences, but they are obsure and SAS admits that "it was a mistake to document them". I've never needed them, but if you're interested, you can find them here.
S={<attribute-definitions>} is what you need if you want to change the characteristics of your output in mid-stream. For example, you might want to highlight a single word in bold or in red. You reset to the default style by using an empty S={} sequence. Here's a simple, turn-the-text-red example.
TITLE "In this title, the word ^S={foreground=RED}red^S={} appears in ^S={foreground=RED}red
TITLE2 "This is an ordinary title";
ODS ESCAPECHAR="^";
Here are links to the full program, log and RTF file.
Notice that in this example, the ODS ESCAPECHAR statement follows the TITLE statements in which it is used. This demonstrates that text is rendered only when the text is rendered in the destination, not when it is first defined.
The S={} ESCAPECHAR sequence is one of the ways in which you can get non-keyboard characters into your output: Set the font to one which contains a glyph for your character. It is the only method that is independent of destination and of character map.
The final use of ESCAPECHAR is one which I presonally don't find very useful. Suppose you want to create versions of your output in two destinations symmultaneously, but you don't want all of the output to appear in both destinations. Then you can use the R ESCAPECHAR sequence to achieve this.
Personally, in this situation, I prefer to run my procedure code twice, and adjust it slightly for each destination. I find the presence of the R ESCAPECHAR sequence just obscures the meaning of the code too much.
Nevertheless, for completeness, here's an example. This example writes a footnote containing the text "This is an RTF file" to the RTF destination and "This is a PostScript file" to the PS destination.
ODS LISTING CLOSE;
ODS RTF BODY="tut0004_2.rtf";
ODS PS BODY="tut0004_2.ps";
ODS ESCAPECHAR="^";
PROC REPORT DATA=SASHELP.Class NOFS;
TITLE "The SASHELP.Class dataset";
COLUMNS Sex Name Age Height Weight;
DEFINE Sex/GROUP;
DEFINE Name/DISPLAY;
DEFINE Age/DISPLAY;
DEFINE Height/DISPLAY;
DEFINE Weight/DISPLAY;
FOOTNOTE "^R/RTF'This is an RTF file'^R/PS'This is a PostScript file'";
BREAK AFTER Sex/PAGE SUPPRESS;
RUN;
ODS RTF CLOSE;
ODS PS CLOSE;
Note that the R ESCAPECHAR is limited. For one, it will never work in the PDF destination. For another, ebven in the RTF destination there are some things, which for technical reasons, it can't do (for example, allow you to adjust the border style of individual cells). Using it can seriously corrupt your output file, even if your SAS jub runs correctly. This may happen if the syntax of your raw code is incorrect. SAS cannot check this for you.
SAS Institute say that the inline formatting commands {super}, {sub}, {dagger} and so on "are the leading edge of what... will eventually become a more open-ended and user-configurable mechanism for formatting functions". I for one can see the possibilities and this is one of the first areas I check for new features with each new release.