Download as docx, pdf, or txt
Download as docx, pdf, or txt
You are on page 1of 24

 Previous Page

 |
 Next Page

Previous Page | Next Page


Using Dynamic Data Exchange under Windows

DDE Examples
This section provides several examples of using DDE with SAS under Windows. These
examples use Microsoft Excel and Microsoft Word as DDE servers, but any application that
supports DDE as a server can communicate with SAS.

Before you run these examples, you must first invoke Microsoft Excel and Microsoft Word,
and open the spreadsheet or document used in the example.

Note:   DDE examples are included in the host-specific sample programs that you access
from the Help menu.  

 Using the X Command to Open a DDE Server

Using DDE to Write Data to Microsoft Excel

Using DDE to Write Data to Microsoft Word

Using DDE to Read Data from Microsoft Excel

Using DDE to Read Data from Microsoft Word

Using DDE and the SYSTEM Topic to Invoke Commands in an Application Using
Excel

Using the NOTAB Option with DDE

Using the DDE HOTLINK

Using the !DDE_FLUSH String to Transfer Data Dynamically

Reading Missing Data

Using the X Command to Open a DDE Server

A DDE server application can be opened using the X command within SAS code. The
XWAIT and XSYNC options must be turned off.

options noxwait noxsync;


x '"c:\microsoft office\office\excel.exe"';

Double quotation marks are required around the path if the path contains a space. The single
quotation marks are for the X command.

Using DDE to Write Data to Microsoft Excel

The first example sends data from a SAS session to an Excel spreadsheet. The target cells are
rows 1 through 100 and columns 1 through 3. To send the data, submit the following
program:

/* The DDE link is established using */


/* Microsoft Excel SHEET1, rows 1 */
/* through 100 and columns 1 through 3 */
filename random dde
'excel|sheet1!r1c1:r100c3';
data random;
file random;
do i=1 to 100;
x=ranuni(i);
y=10+x;
z=x-10;
put x y z;
end;
run;

Using DDE to Write Data to Microsoft Word

This example sends a text string to a Microsoft Word document at a given bookmark. Note
the difference between using DDE with Microsoft Word and Microsoft Excel.

filename testit dde 'winword|"c:\temp\testing.doc"


!MARK' notab;

data _null_;
file testit;
put 'This is a test.';
run;

Note:   If you are writing to Microsoft Word97, use Visual Basic commands such as
FileOpen.Name, FileSave, FileClose, and Insert. If the PUT statement contains a macro that
Word97 does not understand, you will see this message:

Ambiguous name detected: TmpDDE


  

Using DDE to Read Data from Microsoft Excel

You can also use DDE to read data from an Excel application into SAS, as in the following
example:

/* The DDE link is established using */


/* Microsoft Excel SHEET1, rows 1 */
/* through 10 and columns 1 through 3 */
filename monthly
dde 'excel|sheet1!r1c1:r10c3';
data monthly;
infile monthly;
input var1 var2 var3;
run;
proc print;
run;

Using DDE to Read Data from Microsoft Word

This example reads data from a Microsoft Word document at a given bookmark.

filename testit dde 'winword|"c:\temp\testing.doc"


!MARK' notab;

libname workdir 'c:\temp';

/* Get ready to read the first bookmark. */

data workdir.worddata;
length wordnum $5;
infile testit;
input wordnum $;
run;

proc print;
run;

Using DDE and the SYSTEM Topic to Invoke Commands in an Application Using Excel

You can issue commands to Excel or other DDE-compatible programs directly from SAS
using DDE. In the following example, the Excel application is invoked using the X
command; a spreadsheet called SHEET1 is loaded; data are sent from SAS to Excel for row
1, column 1 to row 20, column 3; and the commands required to select a data range and sort
the data are issued. The spreadsheet is then saved and the Excel application is terminated.

/* This code assumes that Excel */


/* is installed on the current */
/* drive in a directory called EXCEL. */

options noxwait noxsync;


x '"c:\microsoft office\office\excel.exe"';

/* Sleep for 60 seconds to give */


/* Excel time to come up. */

data _null_;
x=sleep(60);
run;

/* The DDE link is established using */


/* Microsoft Excel SHEET1, rows 1 */
/* through 20 and columns 1 through 3 */

filename data
dde 'excel|sheet1!r1c1:r20c3';
data one;
file data;
do i=1 to 20;
x=ranuni(i);
y=x+10;
z=x/2;
put x y z;
end;
run;

/* Microsoft defines the DDE topic */


/* SYSTEM to enable commands to be */
/* invoked within Excel. */

filename cmds dde 'excel|system';

/* These PUT statements are */


/* executing Excel macro commands */

data _null_;
file cmds;
put '[SELECT("R1C1:R20C3")]';
put '[SORT(1,"R1C1",1)]';
put '[SAVE()]';
put '[QUIT()]';
run;

Using the NOTAB Option with DDE

SAS expects to see a TAB character placed between each variable that is communicated
across the DDE link. Similarly, SAS places a TAB character between variables when data are
transmitted across the link. When the NOTAB option is placed in a FILENAME statement
that uses the DDE device-type keyword, SAS accepts character delimiters other than tabs
between variables.

The NOTAB option can also be used to store full character strings, including embedded
blanks, in a single spreadsheet cell. For example, if a link is established between SAS and the
Excel application, and a SAS variable contains a character string with embedded blanks, each
word of the character string is normally stored in a single cell. To store the entire string,
including embedded blanks in a single cell, use the NOTAB option as in the following
example:

/* Without the NOTAB option, column1 */


/* contains 'test' and column2 */
/* contains 'one'. */

filename test
dde 'excel|sheet1!r1c1:r1c2';
data string;
file test;
a='test one';
b='test two';
put a $15. b $15.;
run;

/* You can use the NOTAB option to store */


/* each variable in a separate cell. To */
/* do this, you must force a tab */
/* ('09'x) between each variable, as in */
/* the PUT statement. */
/* After performing this DATA step, column1*/
/* contains 'test one' and column2 */
/* contains 'test two'. */

filename test
dde 'excel|sheet1!r2c1:r2c2' notab;
data string;
file test;
a='test one';
b='test two';
put a $15. '09'x b $15.;
run;

Using the DDE HOTLINK

If the HOTLINK option is specified, the DDE link is activated every time the data in the
specified spreadsheet range are updated. In addition, DDE enables you to poll the data when
the HOTLINK option is specified to determine whether data within the range specified have
been changed. If no data have changed, the HOTLINK option returns a record of 0 bytes. In
the following example, row 1, column 1 of the spreadsheet SHEET1 contains the daily
production total. Every time the value in this cell changes, SAS reads in the new value and
outputs the observation to a data set. In this example, a second cell in row 5, column 1 is
defined as a status field. Once the user completes data entry, typing any character in this field
terminates the DDE link:

/* Enter data into Excel SHEET1 in */


/* row 1 column 1. When you */
/* are through entering data, place */
/* any character in row 5 */
/* column 1, and the DDE link is */
/* terminated. */

filename daily
dde 'excel|sheet1!r1c1' hotlink;
filename status
dde 'excel|sheet1!r5c1' hotlink;
data daily;
infile status length=flag;
input @;
if flag ne 0 then stop;
infile daily length=b;
input @;

/* If data have changed, then the */


/* incoming record length */
/* is not equal to 0. */

if b ne 0 then
do;
input total $;
put total=;
output;
end;
run;
It is possible to establish multiple DDE sessions. The previous example uses two separate
DDE links. When the HOTLINK option is used and there are multiple cells referenced in the
item specification, if any one of the cells changes, then all cells are transmitted.

Unless the HOTLINK option is specified, DDE is performed as a single one-time data
transfer. The values currently stored in the spreadsheet cells at the time that the DDE is
processed are values that are transferred.

Using the !DDE_FLUSH String to Transfer Data Dynamically

DDE also enables you to program when the DDE buffer is dumped during a DDE link.
Normally, the data in the DDE buffer are transmitted when the DDE link is closed at the end
of the DATA step. However, the special string '!DDE_FLUSH' issued in a PUT statement
instructs SAS to dump the contents of the DDE buffer. This function allows you considerable
flexibility in the way DDE is used, including the capacity to transfer data dynamically
through the DATA step. The following example creates a Macro Sheet in Microsoft Excel.
Commands are then written to the Macro Sheet, which will rename Sheet1 to NewSheet.
After writing these commands, through the use of !DDE_FLUSH , the Excel Macro can be
executed in the same DATA Step as it is written.

filename cmds dde 'excel|system';


data _null_;
file cmds;
/* Insert an Excel Macro Sheet */
put '[workbook.insert(3)]';
run;

/* Direct the Output to the Newly created Macro Sheet */


filename xlmacro dde 'excel|macro1!r1c1:r5c1' notab;

data _null_;
file xlmacro;
put '=workbook.name("sheet1","NewSheet")';
put '=halt(true)';
/* Dump the contents of the buffer, allowing us to both write and */
/* execute the macro in the same DATA Step */
put '!dde_flush';
file cmds;
/* Run Macro1 */
put '[run("macro1!r1c1")]';
put '[error(false)]';
/* delete the Macro Sheet */
put '[workbook.delete("macro1")]';
run;

Using Macro Variables to Issue DDE Commands

This example illustrates the use of a Macro Variable to issue a command to Microsoft Excel.
In the example, the Macro Variable, excelOne, is being used in place of the Excel Workbook
location C:\test.xls. Since macro triggers such as ampersands and percents are treated as text
within single quotes, a Macro quoting function must be used. %STR is used to mask each
individual apostrophe separately. Anytime you have an unmatched apostrophe or parenthesis
then it must be preceded by a percent sign and since each apostrophe needs to be treated
independently of each other the percents are needed. Once %STR has hidden the apostrophe
the macro variable &excelOne resolves. %UNQUOTE is then used to remove what %STR
has done and restores each apostrophe around the resolved value leaving the result as:

'[open("C:\test.xls")]'
options mprint symbolgen;
filename cmds dde 'excel|system';

%let excelOne=C:\test.xls;

data _null_;
file cmds;
put %unquote(%str(%'[open("&excelOne")]%'));
run;

Reading Missing Data

This example illustrates reading missing data from an Excel spreadsheet called SHEET1.
This example reads the data in columns 1 through 3 and rows 10 through 20. Some of the
data cells can be blank. Here is an example of what some of the data look like:

...
10 John Raleigh Cardinals
11 Jose North Bend Orioles
12 Kurt Yelm Red Sox
13 Brent Dodgers
...

Here's the code that can read these data correctly into a SAS data set:

filename mydata
dde 'excel|sheet1!r10c1:r20c3';
data in;
infile mydata dlm='09'x notab
dsd missover;
informat name $10. town $char20.
team $char20.;
input name town team;
run;
proc print data=in;
run;

In this example, the NOTAB option tells SAS not to convert tabs that are sent from the Excel
application into blanks. Therefore, the tab character can be used as the delimiter between data
values. The DLM= option specifies the delimiter character, and '09'x is the hexadecimal
representation of the tab character. The DSD option specifies that two consecutive delimiters
represent a missing value. The default delimiter is a comma. For more information about the
DSD option, see SAS Language Reference: Dictionary. The MISSOVER option prevents a
SAS program from going to a new input line if it does not find values in the current line for
all the INPUT statement variables. With the MISSOVER option, when an INPUT statement
reaches the end of the current record, values that are expected but not found are set to
missing.

The INFORMAT statement forces the DATA step to use modified list input, which is crucial
to this example. If you do not use modified list input, you receive incorrect results. The
necessity of using modified list input is not DDE specific. You would need it even if you
were using data in a CARDS statement, whether your data were blank- or comma-delimited.

Previous Page | Next Page | Top of Page

Copyright © 2010 by SAS Institute Inc., Cary, NC, USA. All rights reserved.

 Previous Page
 |
 Next Page
 |
 Top of Page
 Here is the simple code which allows us to save the log file in the required
location.

Use Proc printto procedure to save or print the log file.

filename dsn ‘C:\Documents and Settings\zzzzzzzzzzzz\Desktop\


LOGfile.lst';

data dsn;
input patid implants;
datalines;
1 3
1 1
1 2
1 1
2 1
2 2
3 1
4 2
3 1
4 5
2 3
1 6
;run;

proc printto log=dsn new;


run;
 Example 2:
 proc printto log="C:\temp\LOGLOG.log" print="C:\temp\
LSTLST.lst" new;
run;

*Select only male students and age less than 16;


proc sql;
create table males as
select age, height, weight
from sashelp.class
where sex='M' and age lt 16
order by age;
quit;

*Get the descriptive statistics for height variable by


age;

proc means data=males ;


by age;
var height;
output out=htstats mean=mean n=n std=sd median=med
min=min max=max;
run;

PROC PRINTTO; *The second PROC PRINTTO step redirects output back to its
default destination.;
run;

After PROC PRINTTO executes, all procedure output is sent to the alternate
location until you execute another PROC PRINTTO statement or until your program
or session ends.

 Previous Page
 |
 Next Page

Previous Page | Next Page

Directing SAS Log and SAS Procedure Output

Sending E-Mail from within SAS Software

Overview of SAS Support for E-Mail

SAS software enables you to send e-mail by way of a DATA step, SAS procedure, or SCL.
Specifically, you can
 use the logic of the DATA step or SCL to subset e-mail distribution based on a large
data set of e-mail addresses.
 send e-mail automatically upon completion of a SAS program that you submitted for
batch processing.
 direct output through e-mail that is based on the results of processing.

SAS e-mail is implemented in the following language elements:

 the EMAILHOST= and EMAILPORT= SAS options. SAS software sends all e-mail
over a socket to an SMTP server. You or your system administrator might have to
specify the EMAILHOST= system option to identify the host that runs an SMTP
server on your network. The EMAILHOST= option defaults to localhost.The
EMAILPORT= system option identifies the port number on the SMTP server for e-
mail access. The default port number is 25. See "The SMTP E-Mail Interface" in SAS
Language Reference: Conceptsfor more information about SMTP.
 the FILE and FILENAME statements, which are used to specify the name of an e-
mail fileref and the mailing instructions that are used to send it. See FILENAME
Statement, EMAIL (SMTP) Access Method in SAS Language Reference: Dictionary
for details. Options that you specify in the FILE statement override any corresponding
options that you specified in the FILENAME statement.
 the PUT statement, which is used in the DATA step or SCL to create the e-mail
message and to specify or change mailing directives. See PUT Statement Syntax for
E-Mail for details.

PUT Statement Syntax for E-Mail

In your DATA step, after using the FILE statement to define your e-mail fileref as the output
destination, use PUT statements to define the body of the message.

You can also use PUT statements to specify e-mail directives that override the attributes of
your electronic mail message (TO, CC, SUBJECT, TYPE, ATTACH) or perform actions
with it (such as SEND, ABORT, and start a NEWMSG). Specify only one directive in each
PUT statement; each PUT statement can contain only the text associated with the directive it
specifies. Use quotation marks as necessary to construct the arguments of the PUT statement.
However, the final string written by the PUT statement does not need to be enclosed in
quotation marks.

The directives that change the attributes of a message are

!EM_TO! addresses

replaces the current primary recipient addresses with addresses. For example:

PUT "!EM_TO!" "joe@somplace.org";

or
user="joe@somplace.org";
put '!EM_TO!' user;

To specify more than one address, enclose the list of addresses in parentheses and
each address in single or double quotation marks, and separate each address with a
space:

PUT "!EM_TO!" ('joe@smplc.org' 'jane@diffplc.org');

or

list=('joe@smplc.org' 'jane@diffplc.org');
put '!EM_TO!' list;

To specify a name with the address, enclose the address in angle brackets, as follows:

PUT "!EM_TO!" "Joe Smith <joe@somplace.org>";

or

user="Joe Smith <joe@somplace.org>";


put '!EM_TO!' user;
!EM_CC! addresses

replaces the current copied recipient addresses with addresses. For example:

PUT "!EM_CC!" "joe@somplace.org";

or

user="joe@somplace.org";
put '!EM_CC!' user;

To specify more than one address, enclose the list of addresses in parentheses and
each address in single or double quotation marks, and separate addresses with a space:

PUT "!EM_CC!" ('joe@smplc.org' 'jane@diffplc.org');

or

list=('joe@smplc.org' 'jane@diffplc.org');
put '!EM_CC!' list;

To specify a name with the address, enclose the address in angle brackets, as follows:

PUT "!EM_CC!" "Joe Smith <joe@somplace.org>";

or

user="Joe Smith <joe@somplace.org>";


put '!EM_CC!' user;
!EM_BCC! addresses
replaces the current blind copied recipient addresses with addresses. For example:

PUT "!EM_BCC!" "joe@somplace.org";

or

user="joe@somplace.org";
put '!EM_BCC!' user;

To specify more than one address, enclose the list of addresses in parentheses and
each address in single or double quotation marks, and separate addresses with a space:

PUT "!EM_BCC!" ('joe@smplc.org' 'jane@diffplc.org');

or

list=('joe@smplc.org' 'jane@diffplc.org');
put '!EM_BCC!' list;

To specify a name with the address, enclose the address in angle brackets, as follows:

PUT "!EM_BCC!" "Joe Smith <joe@somplace.org>";

or

user="Joe Smith <joe@somplace.org>";


put '!EM_BCC!' user;
!EM_FROM! 'address'

replaces the current address of the sender of the message with address. For example:

PUT "!EM_FROM! "john@hisplace.org"

or

user="john@hisplace.org";
put '!EM_FROM!' user;
!EM_SUBJECT! subject

replaces the current subject of the message with subject.

!EM_CONTENTTYPE! content-type

replaces the current content type of the message with content-type.

!EM_ATTACH! "file-specification"

replaces the current list of attachments with file-specification. Enclose the file-
specification in double quotation marks.
To attach more than one file or a file with additional attachment options, enclose the
list of file specifications or options in parentheses and separate each file-specification
with a space. The attachment options are

CONTENT_TYPE='content/type'

specifies the MIME content type that should be associated with this attachment. The
default content type is text/plain. CONTENT_TYPE= can be specified as:

 CONTENT_TYPE=
 CONTENT-TYPE=
 TYPE=
 CT=

EXTENSION='extension'

specifies the filename extension on the recipient's file that is attached. This extension
is used by the recipient's e-mail system for selecting the appropriate utility to use for
displaying the attachment. The default attachment extension is "txt". EXTENSION=
can be specified as EXT=.

NAME='name'

specifies a different name to be used for the attachment.

The following examples show the syntax for specifying attachment options in a PUT
statement:

put '!EM_ATTACH!' "('user.misc.pds(member)' content_type='text/html'


extension='html')";

put '!EM_ATTACH!' "('user.misc.jcl(sasjcl)' extension='doc',


'userid.sas.output' content_type='image/gif'
extension='gif'
name='Test Results')";

mycfg="'user.misc.jcl(sasjcl)'";
syscfg="'user.sas.output' content_type='image/gif' ext='gif'";
put '!EM_ATTACH!' "("mycfg","syscfg")";

These directives perform actions:

!EM_SEND!

sends the message with the current attributes. By default, SAS sends a message when
the fileref is closed. The fileref closes when the next FILE statement is encountered or
the DATA step ends. If you use this directive, SAS software sends the message when
it encounters the directive and again at the end of the DATA step.

!EM_ABORT!
stops the current message. You can use this directive to stop SAS software from
automatically sending the message at the end of the DATA step.

!EM_NEWMSG!

clears all attributes of the current message, including TO, CC, SUBJECT, TYPE,
ATTACH, and the message body.

Example: Sending E-Mail from the DATA Step

Suppose you want to share a copy of your SASV9 CONFIG file with your coworker Jim,
whose user ID is JBrown. You could send it by submitting the following DATA step:

filename mymail email 'JBrown@ajax.com'


subject='My SASV9 CONFIG file'
attach="jbrown.tso.config(sasV9)";

data _null_;
file mymail;
put 'Jim,';
put 'This is my SASV9 CONFIG file.';
put 'I think you might like the new options I added.';
run;

The following example sends a message and two attached files to multiple recipients. It
specifies the e-mail options in the FILE statement instead of in the FILENAME statement:

filename outbox email 'ron@acme.com';

data _null_;
file outbox
to=('ron@acme.com' 'lisa@acme.com')
/* Overrides value in */
/* filename statement */

cc=('margaret@yourcomp.com'
'lenny@laverne.abc.com')
subject='My SAS output'
attach=("my.sas.output" "my.sas.code")
;
put 'Folks,';
put 'Attached is my output from the
SAS program I ran last night.';
put 'It worked great!';
run;

You can use conditional logic in the DATA step to send multiple messages and to control
which recipients receive which message. For example, suppose you want to send customized
reports to members of two different departments. Here is a DATA step example:

filename reports email 'Jim@corp.com';

data _null_;
file reports;
infile cards eof=lastobs;
length name dept $ 21;
input name dept;
put '!EM_TO!' name;
/* Assign the TO attribute */

put '!EM_SUBJECT! Report for ' dept;


/* Assign the SUBJECT attribute */

put name ',';


put 'Here is the latest report for ' dept '.';
if dept='marketing' then
put '!EM_ATTACH!' "userid.market.report";
else
/* ATTACH the appropriate report */

put '!EM_ATTACH!' "userid.devlpmnt.report";


put '!EM_SEND!';
/* Send the message */

put '!EM_NEWMSG!';
/* Clear the message attributes */

return;
lastobs: put '!EM_ABORT!';
/* Abort the message before the */
/* RUN statement causes it to */
/* be sent again. */

datalines;
Susan marketing
Jim marketing
Rita development
Herb development
;
run;

The resulting e-mail message and its attachments are dependent on the department to which
the recipient belongs.

Note:   You must use the !EM_NEWMSG! directive to clear the message attributes between
recipients. The !EM_ABORT! directive prevents the message from being automatically sent
at the end of the DATA step.  

Sending Procedure Output as E-Mail

Overview of Sending Procedure Output as E-Mail

E-mail can be used to send procedure output. ODS HTML procedure output must be sent
with the RECORD_SEPARATOR (RS) option set to NONE. For z/OS, ODS produces an
HTML stream with embedded record-separator characters, by default. When the RS option is
set to NONE, ODS writes one line of HTML at a time to the file. Make sure that the file's
record length is large enough to accommodate the longest HTML line.

The following section contains examples that illustrate how to send ODS HTML and graph
output in the body of an e-mail message and also as attachments to e-mail.

Examples: Sending Procedure Output via E-Mail

The following example shows how to use ODS to send HTML output in e-mail:

filename outbox email


to='susan@mvs'
type='text/html'
subject='Temperature conversions'
;

data temperatures;
do centigrade = -40 to 100 by 10;
fahrenheit = centigrade*9/5+32;
output;
end;
run;

ods html
body=outbox /* Mail it! */
rs=none;

title 'Centigrade to Fahrenheit conversion table';


proc print;
id centigrade;
var fahrenheit;
run;

ods html close;

The following example shows how to create and send a GIF image in an e-mail message:

filename gsasfile email


to='Jim@acme.com'
type='image/gif'
subject="SAS/GRAPH output."
;

goptions dev=gif gsfname=gsasfile;

proc gtestit pic=1; run;

The following example shows how to create ODS HTML and send it as attachments to an e-
mail message:

/* ---------------------------------------- */
/* allocate PDSE to contain the HTML output */
/* ---------------------------------------- */
filename odsout '.mvsmail1.pdse' disp=(new,catlg,delete)
dsorg=po dsntype=library;
/* ------------------------------------ */
/* stop sending output to OUTPUT window */
/* ------------------------------------ */
ods listing close;

/* ----------------------------------------------------- */
/* Assign frame, contents and body files. */
/* Specify the URLs to have the .html extension. */
/* Specify the PATH to be the PDSE. */
/* Specify RS=NONE to write one line of HTML per record. */
/* This is necessary when e-mailing the HTML output. */
/* ----------------------------------------------------- */
ods html frame='shoes1f'
contents='shoes1c' (url='shoes1c.html')
body='shoes1b' (url='shoes1b.html')
path=odsout
rs=none;

data newshoes;
set sashelp.shoes;
where Region in ('Canada' 'Central America/Caribbean'
'South America' 'United States');
run;

/* ----------------------------------------- */
/* sort the data set and generate the report */
/* ----------------------------------------- */
proc sort data=newshoes;
by Region Subsidiary Product;
run;

options nobyline;
title1 'Sales for Regions #byval(Region)';
proc report data=newshoes nowindows;
by Region;
column Region Product Subsidiary Sales;
define Region / noprint group;
define Product / display group;
define Subsidiary / display group;
define Sales / display sum format=dollar8.;
compute after Region;
Product='Total';
endcomp;
break after Region / summarize style=rowheader;
run;

/* ------------------------------------------------------ */
/* Close the HTML destination and open the listing output */
/* ------------------------------------------------------ */
ods html close;
ods listing;

/* ----------------- */
/* E-mail the report */
/* ----------------- */
filename email email 'fred@bedrock.com'
subject="Shoe report 1"
type="text/plain"
attach=(".mvsmail1.pdse(shoes1f)" content_type='text/html' extension='html'
".mvsmail1.pdse(shoes1c)" content_type='text/html' extension='html'
".mvsmail1.pdse(shoes1b)" content_type='text/html'
extension='html') ;
data _null_;
file email;
put 'Here is the latest Shoe sales report';
run;

The following example shows how to create ODS HTML and GIF files and send them as e-
mail attachments:

/* ------------------------------------------------ */
/* Define the UNIX System Services USS directory to */
/* contain the graphics and HTML output. */
/* ------------------------------------------------ */
filename odsout '/u/myhome/public_html';

/* ------------------------------------------------ */
/* stops sending output to GRAPH and OUTPUT windows */
/* ------------------------------------------------ */
ods listing close;

/* ---------------------------- */
/* set the graphics environment */
/* ---------------------------- */
goptions reset=global gunit=pct
colors=(black blue green red)
hsize=8.42 in vsize=6.31 in ftitle=zapfb
ftext=swiss htitle=4 htext=2.5
device=gif transparency noborder;

/* --------------------------------- */
/* add the HTML variable to NEWSHOES */
/* --------------------------------- */
data newshoes;
set sashelp.shoes;
where Region in ('Canada' 'Central America/Caribbean'
'South America' 'United States');
length regdrill $40;

if Region='Canada' then
regdrill='HREF="shoes1_regsales.html#IDX1"';

else if Region='Central America/Caribbean' then


regdrill='HREF="shoes1_regsales.html#IDX2"';

else if Region='South America' then


regdrill='HREF="shoes1_regsales.html#IDX3"';

else if Region='United States' then


regdrill='HREF="shoes1_regsales.html#IDX4"';

run;

/* ------------------------------------------------------*/
/* Assign the destination for the ODS graphics output */
/* and ODS HTML files. */
/* Specify RS=NONE to write one line of HTML per record. */
/* This is necessary when e-mailing the HTML output. */
/* ----------------------------------------------------- */
ods html path=odsout
body='shoe_report.html'
rs=none
nogtitle;

/* ----------------------------------- */
/* define title and footnote for chart */
/* ----------------------------------- */
title1 'Total Sales for the Americas';
footnote1 h=3 j=l 'click on bars' j=r 'REPORT3D ';

/* ----------------------------------- */
/* assign a pattern color for all bars */
/* ----------------------------------- */
pattern color=cyan;

/* --------------------------- */
/* define axis characteristics */
/* --------------------------- */
axis1 order=(0 to 7000000 by 1000000)
minor=(number=1)
label=none;
axis2 label=none offset=(4,4)
value=('Canada' 'C. Amr./Car.'
'S. America' 'USA');

/* --------------------------- */
/* generate vertical bar chart */
/* --------------------------- */
proc gchart data=newshoes;
vbar3d Region / discrete
width=6
sumvar=sales
html=regdrill
coutline=black
cframe=blue
maxis=axis2
raxis=axis1
name='shoes1 ';
run;
quit;

/* ----------------------------------------------------- */
/* Open the HTML destination for the PROC PRINT output. */
/* Specify RS=NONE to write one line of HTML per record. */
/* This is necessary when e-mailing the HTML output. */
/* ----------------------------------------------------- */
ods html body='shoes1_regsales.html'
rs=none
path=odsout;

/* ----------------------------------------- */
/* sort data set NEWSHOES in order by region */
/* ----------------------------------------- */
proc sort data=newshoes;
by Region Subsidiary Product;
run;
quit;

/* -------------------------------------------- */
/* print a report of shoe sales for each Region */
/* -------------------------------------------- */
goptions reset=footnote;
option nobyline;
title 'Sales Report for #byval(Region)';
proc report data=newshoes nowindows;
by Region;
column Region Subsidiary Product Sales;
define Region / noprint group;
define Subsidiary / display group;
define Product / display group;
define Sales / display sum format=dollar12.;
compute after Region;
Subsidiary='Total';
endcomp;
break after Region / summarize style=rowheader page;
run;

/* ------------------------------------------------------ */
/* Close the HTML destination and open the listing output */
/* ------------------------------------------------------ */
ods html close;
ods listing;

/* ---------------- */
/* Email the report */
/* -----------------*/
filename email email 'barney@bedrock.com'
subject="Shoe report 2"
type="text/plain"
attach=("./public_html/shoe_report.html" content_type='text/html'
"./public_html/shoes1_regsales.html" content_type='text/html'
"./public_html/shoes1.gif" content_type='image/gif') ;
data _null_;
file email;
put 'Here is the latest Shoe sales report';
run;

Example: Directing Output as an E-Mail Attachment with Universal Printing

Follow these steps to send procedure output as an attachment to an e-mail message.

1. Define a Universal printer with a device type of 'EMAIL'.


2. Establish a printing destination with the PRINTERPATH= option:

options printerpath='emailjoe';

The OPTIONS statement assigns EMAILJOE as the default Universal printer.


EMAILJOE remains the default printer for the duration of the SAS session, unless it
is overridden by another OPTIONS statement.

3. Identify the print destination to SAS:

ods printer;
The ODS PRINTER statement enables procedure output to be formatted for a high-
resolution printer. Because the ODS PRINTER statement does not specify a filename
or fileref, ODS output is sent to the Universal Printing default printer (EMAILJOE).

4. Issue a print command or procedure:


5. proc print data=sashelp.shoes;
6. where region="Canada";
run;

PROC PRINT generates procedure output in standard ODS format. The output is sent
to the attachment file associated with EMAILJOE.

7. Remove the print destination:

ods printer close;

The second ODS PRINTER statement removes the ODS print destination. The
procedure output is sent to EMAILJOE, which sends the e-mail message with the
attached file to the e-mail recipient.

The following program defines a registry entry for printing procedure output to an e-mail
attachment:

/* STEP 1 */
data printers;
name = 'emailjoe';
protocol = 'Ascii';
trantab = 'GTABCMS';
model = 'PostScript Level 1 (Gray Scale)';
device = 'EMAIL';
dest = 'John.Doe@sas.com';
hostopt = "recfm=vb ct='application/PostScript'
subject='Canada Report' ";
run;

/* STEP 2 */
proc prtdef data=printers replace list;
run;

Example: Sending E-Mail by Using SCL Code

The following example is the SCL code that underlies a frame entry design for e-mail. The
frame entry includes these text-entry fields:

mailto the user ID of the e-mail recipient

copyto the user ID of the recipient of the e-mail copy (CC)

attach the name of the file to attach


subject the subject of the e-mail message

line1 the text of the e-mail message

The frame entry also contains a push button named SEND that causes this SCL code (marked
by the send: label) to execute.

send:

/* set up a fileref */

rc = filename('mailit','userid','email');

/* if the fileref was successfully set up


open the file to write to */

if rc = 0 then do;
fid = fopen('mailit','o');
if fid > 0 then do;

/* fput statements are used to


implement writing the
mail and the components such as
subject, who to mail to, etc. */

fputrc1 = fput(fid,line1);
rc = fwrite(fid);

fputrc2 = fput(fid,'!EM_TO! '||mailto);


rc = fwrite(fid);
fputrc3 = fput(fid,'!EM_CC! '||copyto);
rc = fwrite(fid);

fputrc4 = fput(fid,'!EM_ATTACH! '||attach);


rc = fwrite(fid);
fputrc5 = fput(fid,'!EM_SUBJECT! '||subject);
rc = fwrite(fid);

closerc = fclose(fid);
end;
end;
return;

cancel:
call execcmd('end');
return;

 Home
 About
 Contact
 Products
 Services
 BI University
 SAS Potpourri
 SAS Video Demos

How to e-mail SAS Log files


Did you ever want the log file from a SAS batch job to be saved with the date and time that
the job ran and/or be e-mailed to a recipient or group of recipients. At least for Windows/SAS
environments, here's the secret below:

Step 1

Set up a SAS program that gets called from a batch file that gets called from each batch file
that runs a SAS program. It should look something like the following:

/* Set two SAS macro variables from environment variables */

%let sasmail=%sysget(sasmail);

%let saslog=%sysget(saslog);

Filename OUTBOX EMAIL ' ' ; /* Set up filename for email */

Data _null_ ;

File OUTBOX /* Use Filename defined above */

TO=(&sasmail) /* Get recipient address */

Attach=("&saslog") /* Attach the log file */

Subject="Log file &saslog"; /* Add a subject */

Put "SAS log file is attached" ; /* Goes in the body */

Run;

Step 2

Set up a batch file to call the above SAS program. It should look something like the one
below:

rem Put actual email address of recipeint(s) below


set sasmail="you@email.com" "another@email.com"

rem Copy the original sas log to one that has the date and time appended (for future
reference)
copy "%saslog%"
"%saslog%%date:~-4,4%-%date:~-10,2%-%date:~-7,2%-%time:~-11,2%%time:~-8,2%
%time:~-5,2%.log"

rem Call the sas process that emails the above log as an attachemnt to the email address(ees)
above.
"D:\SAS\SAS 9.1\sas.exe" "F:\SAS ETL Jobs\sendemail.sas" -config "D:\SAS\SAS 9.1\nls\
en\SASV9.CFG"
-log "F:\SAS ETL Jobs\logs\sendemail.log"

Step 3

In each of the SAS bat files that call .sas programs, insert two lines:

1. One to set an environment variable for the name of the log file.
2. One to call the bat file from step 2 that processes the log files.

An example follows:

rem This process run the SAS process in batch suitable for scheduling

set saslog=F:\SAS ETL Jobs\logs\SasProgram_ETL.log

"D:\SAS\SAS 9.1\sas.exe" "F:\SAS ETL Jobs\SasProgram_ETL.sas" -config "D:\SAS\SAS 9.1\nls\en\


SASV9.CFG" -log "%saslog%"

call "F:\SAS ETL Jobs\ProcessLog.bat"

That's it. Enjoy

Home | About |  Contact | Products | Services | BI University | SAS Potpourri | SAS Video
Demos | Site Map

Copyright © 2009 Blue Chip Solutions Inc. All Rights Reserved.

You might also like