Vous êtes sur la page 1sur 9

NESUG 2010

Applications Development

SAS Email Data Driven Application


Wenjie Wang, Sun Solutions Inc, Clinton, NJ Jade Huang, Merck & Co., Inc., Rahway, NJ Simon Lin, Eisai Inc., Woodcliff Lake, NJ
ABSTRACT
In the business world, emails are a common and relied upon method of communication. For people who work with SAS, the SAS EMAIL access method offers a convenient way to distribute a query result via email. This paper presents a useful technique on how to dynamically create the query report for the corresponding recipient and automate sending of a message with the attached file to numerous addressees on a regular basis. The targeted audiences are intermediate or advanced users of SAS. SAS Version 8.2 or 9.1, Windows XP Key Words: SAS, DATA step, FILENAME statement, EMAIL access method.

INTRODUCTION
Sending out bulk emails to multiple recipients with corresponding attachments from email software such as Microsoft Outlook is not an easy task. Bulk emails can be error-prone as it is not unheard of to inadvertently attach and send an incorrect file to the wrong recipient. With SASs data step and EMAIL facilities, the email task can be automated with the simple implementation of SAS code. This paper presents an easy data driven SAS email application using SAS EMAIL capabilities.

SAS EMAIL ACCESS METHOD BASICS


System Configuration: Following is a list of SAS Email related system options: EMAILSYS, EMAILHOST, EMAILPORT, EMAILID, and EMAILPW. These are the values that are supported by EMAIL Access Method for system option EMAILSYS: o MAPI: Messaging Application Program Interface (interface supported by Windows and Windows NT, which is used by Microsoft Exchange. MAPI is the default.) o VIM: Vendor Independent Mail such as Lotus or cc:Mail. The statement below can be issued to determine the value for a system: proc options option=emailsys; run; Log: EMAILSYS=MAPI Used by E-mail Access Method and Send menu item to set the interface type with underlying e-mail system. If a system supports the Email Access Method, sending emails from within a SAS session can be achieved. Syntax: FILENAME fileref EMAIL 'address' <email-options>; fileref : is a valid fileref o EMAIL: is the device-type keyword that indicates the request to use email o 'address' : is the valid destination email address of the user for the email recipient o email-options specify the recipient's email address, subject, cc recipient's email address, and attachment files Options specified in the FILE statement inside the DATA step can override any corresponding options that were specified in the FILENAME statement. Common directives to specify the message attributes in the DATA step PUT statement are: o !EM_TO! addresses o !EM_CC! addresses o !EM_SUBJECT! Subject o !EM_ATTACH! filename.ext The following are the common directives that perform actions: o !EM_SEND!: sends the message with the current attributes o !EM_ABORT!: aborts the current message o !EM_NEWMSG!: clears all attributes of the current message that were set using PUT statement directives

NESUG 2010

Applications Development

Example 1: The following example shows how to issue a simple message with an attachment file using the FILENAME options: filename outmail email "xiqun@yahoo.com" subject="Lab Outlier Report.doc" cc="xiqun_huang@merck.com" attach="c:\reports\Lab Outlier Report.doc"; data _null_; file outmail; put 'Dear Investigator,'; put 'Attached is your site Lab Outlier Report for study 0938-45'; put 'Please check and let me know if you have any question'; put; put 'Regards,'; put; put 'Jade Huang'; run; Screen shot from Outlook:

Example 2: Use Email options specified in FILE statement to override the options in a FILENAME statement. filename outmail email "xiqun@yahoo.com" ; data _null_; file outmail to="wenjie.wang@klconsultingservices.com" cc="xiqun_huang@merck.com" subject="Invoice Report.doc" attach="c:\reports\Invoice report.doc" ; put 'Dear Wenjie'; put 'Attached is your last month invoice report.'; put 'If you have any question, please feel free to call.'; put; put 'Regards,'; put 'Jade Huang'; run; The following screen shot shows that the option in the FILENAME statement is overwritten.

NESUG 2010

Applications Development

Example 3: The directives in the PUT statement will override the corresponding option defined at the FILENAME or FILE statement as shown below. filename outmail email ; data _null_; file outmail; PUT '!EM_TO! wenjie.wang@klconsultingservices.com'; PUT '!EM_SUBJECT! Reminder'; PUT '!EM_CC! xiqun_huang@merck.com'; PUT '!EM_ATTACH! c:\reports\Insurance Claim Report.doc'; put 'Dear Accountant,'; put 'This is a reminder, please process the attached invoice within'; put '7 days to claim money from the insurance provider.'; put; put 'Regards,'; put; put 'Jade Huang'; run;

SAS EMAIL DATA DRIVEN APPLICATION


Sending files to various people on a regular basis through Outlook can be difficult and may result in such errors as sending incorrect files to the wrong person. With the SAS data step and the directive commands, the user can dynamically modify the email option based on each observation of the input dataset. Example: Use SAS dataset and directives in put statements to automate the task. recipient email_address attach_file cc_address Wenjie Wang wenjie.wang@ u:\2009\Registration xiqun_huang@ klconsultingservices.com Report.doc merck.com filename myemail email; data _null_; set indata.ex4; *input sas dataset; file myemail; * use input dataset variables in directives to specify the attributes; put '!EM_TO!' email_address; PUT '!EM_CC!' cc_address; put '!EM_SUBJECT! Registration Report for ' recipient; put '!EM_ATTACH! ' attach_file; put "Dear " recipient ":" ; put 'Attached please find your Registration Report.'; put 'Regards,'; put 'Jade Huang'; run;

NESUG 2010

Applications Development

The following is an example of a requirement for a SAS Email Application: In a hospital, there are SOPs regarding Residents Notes Writing which regulate that each attending resident physician write a note within 24 hours of each admission; the notes could be written by his/her assistant or nurse. If he/she did not write notes within 24 hours of an admission, at the end of that week, he/she will get an email with an attachment which shows the admission case lacking notes. This process can be automated with the emanagement tool to increase the SOP compliance rate; macros are used to accomplish this task. The macro will have two parameters called FROM and TO which denote the report period from which to extract data; the detail coding is in the appendix. Input dataset- NOTE: Note_EIN could be either a doctor or nurse employee identifier

Input dataset- ADMISSION: Here ADM_EIN is the attending Physician identification number

Input dataset: EMP

SAS Email Application Process Flow Chart


Noncompli (Non compliance admission cases): ein, admission_dt, patientid, patientname ,Ward, room_bed ,delay
Noncompli_ein(Physicians who are not in compliance): Ein, Firstname, Lastname,Email_address

Emp (Employer information): Employee EIN, first, last name, email address, etc

Execute macro %macro update_noncompli_email For each non compliant EIN

Send out bulk emails with attachments using Dataset- Noncompli_email_list

Populate the dataset- Noncompli_email_list: Ein, Emp_name, email_address, attach_file

SAS Email Application Procedure: 1. Prepare Data: noncompli & noncompli_ein

NESUG 2010

Applications Development

Merge the admission and notes files and select the admission cases which lack notes during a certain week range(Noncompli dataset) based on the two macro parameters: from date and to date in the format of DATE9. Find out the physicians who are not in compliance: Noncompli_ein ein 1002 firstname Wenjie lastname Wang email_address wenjie.wang@klconsultingservices.com

2. %macro update_noncompli_email_list: generate an rtf file associated with each attending physician's non-compliant admission cases and populate the noncompli_email_list table for sending out email later on. This part is the key part of the application. o Compile %macro update_noncompli_email_list( ) o Prepare noncompli_email_list table structure: Ein o emp_name email_address attach_file

Execute the macro %update_noncompli_email_list to populate the dataset non_compli_email_list based on each iteration of the input dataset noncompli_ein:

Data _NULL; set noncompli_ein;

ein

firstname

lastname

email_address

/* use execute routine to pass each observation to a macro from data step */ call execute( '%update_noncompli_email_list(ein='||ein|| ',Physician_name='||compress(firstname)|| '_'||compress(lastname)|| ', name='||compress(firstname)|| ' '||compress(lastname)|| ', email_address='||compress(email_address)|| ') ); RUN; %MACRO update_noncompli_email_list( ein= , physician_name= , name= , email_address=); filename attfile "c:\ Admission_Audit_Report_for_&physician_name._ Wkof&to..rtf"; ods listing close; ods rtf file= attfile bodytitle; %* create attachment for each selected non compliant physician, the output screen shot is as follows; Admission Audit Report for Wenjie Wang from 20JUL2009 to 27JUL2009 The following is a list of admissions which has no notes as of 28JUL2009 Room and Bed

Admission Date/Time Patient ID Patient Name

Ward

Reason No Notes

20JUL2009:08:01:00 789098099 James Patterson Internal B00301-A 20JUL2009:09:01:00 235345691 Lisa Lowers 21JUL2009:11:20:00 987098000 Brian Jacquers ods rtf close; ods listing; %* insert into noncompli_email_list ; Ein emp_name email_address 1002 Wenjie wenjie.wang@klcons Wang ultingservices.com %MEND update_noncompli_email_list; 3. Email with an attachment using noncompli_email_list dataset as input: filename myemail email; data _null_;

Internal B00301-B Delayed Notes Internal B00302-B No Notes

attach_file c:\paper\Admission_Audit_Report_fo r_Wenjie_Wang_Wkof27JUL2009.rtf

NESUG 2010

Applications Development

set noncompli_email_list; %* input dataset; .. Run; Screen shot of the email sent by the application:

4. To further automate the procedure, put it in Windows Scheduler or Unix Cron Job.

CONCLUSION
SAS Email Access Method combined with the powerful language of SAS can turn a lengthy repetitive administrative task into a quick and error-proof job. The macro demonstrated above is very flexible and easy to modify and can be implemented to fit your business needs.

REFERENCE
Using Groupware to Distribute SAS Data at April 2009 http://v8doc.sas.com/sashtml/ Wenjie Wang and Simon Lin Using SAS to Send Bulk Emails with Attachments Proceedings of the Pharmaceutical Industry SAS Users, May 2007 ACKNOWLEDGMENTS SAS and all other SAS Institute Inc. product or service names are registered trademarks or trademarks of SAS Institute Inc. in the USA and other countries. indicates USA registration. Other brand and product names, such as Microsoft Outlook are registered trademarks or trademarks of their respective companies.

CONTACT INFORMATION
Wenjie Wang Programmer Consultant Sun Solutions Inc, Clinton, NJ (908) 660-4933 Wwang9235@gmail.com Jade Huang Merck & Co., Inc. (732) 594-3854 xiqun_Huang@merck.com Simon Lin Eisai Inc. (201) 627-2866 Simon_lin@eisai.com

APPENDIX
libname indata "u:\2009\paper"; %macro notes_report(from=, to=); %let today=%sysfunc(today(),date9.); /* capture report running date*/ %********************************************************************; %* Step 1: get the admission file and notes file *; %********************************************************************;

NESUG 2010

Applications Development

proc sort data=indata.admission(where=(input("&from", date9.)<=datepart(admission_dt)<=input("&to", date9.))) out=admission; by adm_caseid; run; proc sort data=indata.notes(where=(input("&from", date9.)<=datepart(notes_dt)<=input("&to", date9.)+1)) out=notes; by adm_caseid; run; %********************************************************************; %* Step 2: merge the two files to get the admission case which lack *; %* notes or has delayed notes *; %********************************************************************; %* for each admission, there should have a note associated with it *; data allnotes; merge admission(in=a) notes(in=b drop=patientid patientname); by adm_caseid; tminterval=intck('hour',admission_dt, notes_dt); if intck('hour',admission_dt, notes_dt)>24 then do; notes=1; compliance=0; delay=1; end; else if intck('hour',admission_dt, notes_dt)= . then do; notes=0; compliance=0; delay=.; end; else if intck('hour',admission_dt, notes_dt) <=24 then do; notes=1; compliance=1; delay=0; end; else compliance=.; run; data noncompli; set allnotes; where delay ne 0; run; proc format; value delayf 1="Delayed Notes" .="No Notes"; run; %********************************************************************; %* Step 3: create a macro to generate a rtf file for each attending *; %* physician who did not write a notes or delayed in notes *; %* writing, and in the mean time, populate the *; %* noncompli_email_list table for sending out email later on*; %********************************************************************; %macro update_noncompli_email_list( ein=, physician_name=, name=, email_address=); %* get the attending physician name, email address and save them *;

NESUG 2010

Applications Development

%* to macro variable *; filename attfile"u:\2009\paper\Admission_Audit_Report _for_&physician_name._Wkof&to..rtf"; ods listing close; ods rtf file= attfile bodytitle; title1 "Admission Audit Report for &name from &from to &to."; title2 "The following is a list of admission which has no notes or delayed notes as of &today"; proc sql; select admission_dt label='Admission Date/Time', patientid label='Patient ID', patientname label='Patient Name', ward label='Ward', room_bed label='Room and Bed', delay label='Reason' format=delayf. from noncompli where ADM_EIN=&ein; quit; ods rtf close; ods listing; %*** Now populate the nonotes_email_list table ***; proc sql; insert into noncompli_email_list values (&ein, "&name", "&email_address", "u:\2009\paper\Admission_Audit_Report_for_&physician_name._Wkof&to. .rtf"); quit; %mend update_noncompli_email_list; %********************************************************************; %* Step 4: find out how many physician is not in compliance *; %********************************************************************; proc sort data=noncompli out=noncompli_adm_ein(keep=adm_ein) nodupkey; by adm_ein; run; proc sql; create table noncompli_ein as select a.* from indata.emp as a, noncompli_adm_ein as b where a.ein=b.adm_ein ; quit; %********************************************************************; %* Step 5: execute macro to generate the report for each *; %* non-compliant physician and update the *; %* non_compli_email_list dataset with the name and location *; %* for each report file, email_address,physician name, etc. *; *; %********************************************************************; proc sql; drop table noncompli_email_list; create table noncompli_email_list (ein num, emp_name char(60), email_address char(60), attach_file char(100)); quit; Data _null; set noncompli_ein; /* executing macro: update_noncompli_email_list from data step */

NESUG 2010

Applications Development

call execute('%update_noncompli_email_list(ein='||ein|| ',Physician_name='||compress(firstname)|| '_'||compress(lastname)|| ', name='||compress(firstname)|| ' '||compress(lastname)|| ', email_address='||compress(email_address)|| ')' ); run; %********************************************************************; %* Step 6: Send email to each non-compliant physician with the *; %* corresponding attachment *; %********************************************************************; filename myemail email; data _null_; set noncompli_email_list; file myemail; put '!EM_TO!' email_address; put '!EM_SUBJECT! Admission Audit Report for ' emp_name; put "Dear Provider " emp_name ":" ; put "According to the medical record, you are either the "; put "inpatient attending physician or the attending in "; put "charge of the ward for the patient(s) listed below. "; put "An attending admission note is required by policy "; put "within one calendar day from the time of admission, "; put "but could not be found for the patient(s) listed. "; put "Please place your attending note in system ASAP. "; put "Thank you for your attention. "; put '!EM_ATTACH!' attach_file; put '!EM_SEND!'; put '!EM_NEWMSG!'; put '!EM_ABORT!'; run; %mend notes_report; %notes_report(from=20JUL2009, to=27JUL2009);

Vous aimerez peut-être aussi