Sie sind auf Seite 1von 5

NESUG 15

Applications Development

SAS Output to Excel: DDE and Beyond Lawrence Helbers, Omnicare Clinical Research, King of Prussia, PA Alex Vinokurov, Omnicare Clinical Research, King of Prussia, PA

Some clients require SAS data to be displayed in formatted MS Excel spreadsheets. This paper describes the development of a SAS macro that supports a variety of table layouts and avoids many manual-formatting steps in Excel. Output features covered include: font control, column width, data formats, alignment, page setup, spanned headers, borders and file operations. This SAS macro has been developed to write and format the spreadsheet in a single call that can be included in your data preparation programs. The macro was developed using DDE techniques in SAS v6.12 and SAS v8.2 on the MS Windows platform. With a forthcoming platform change to UNIX and Enterprise Guide software and the new features afforded by ODS in SAS v8, the paper also discusses adapting to change.

ABSTRACT

OUTPUT FORMAT REQUIREMENTS


The utility should be able to automatically: Open and close (save) the spreadsheet Setup the page orientation, centering, fitting, margins Apply different column widths to the data Control font size and style of titles, heading, body Apply custom data fonts Center titles Span header labels Align data center, left, right Print titles, headers, footnotes Apply line drawing (borders)

The objective is to eliminate performing these steps manually, saving time and improving consistency.

INTRODUCTION
Useful applications sometimes evolve rather than being developed from a strict set of user requirements. Thats what happened here. A client wanted output in Excel spreadsheets because he preferred the look, liked the ease of use and wanted the flexibility to manipulate the output mathematically. We developed one macro, then another and so on. After solving many individual problems, we were able to step back and see how we might generalize the code . This paper builds on sample SAS programs and prior user-group presentations on using DDE (Dynamic Document Exchange) with SAS and Excel. Interested readers will find it provides additional details about formatting commands syntax and how to introduce macro variables into commands that have embedded quotes. Certain design choices were made because of the need to produce hundreds of tables for many different projects with different layouts. The resultant macro produces a variety of formatted spreadsheets. This is now in use as a general utility in our programming and we are no longer proliferating table specific macros to write Excel. It has saved time and produced more consistent output than prior, manually-formatted output. Although its actual development was by evolution, to simplify exposition we'll proceed as if we started with design requirements, did an assessment of design alternatives, developed external specification for the macro call and then present the resulting code. The paper closes with a discussion of how we are reacting to external change brought about by a change in platforms and access.

The utility should be able to produce spreadsheet output for the following general table layouts, which cover the majority of requests received. ROW LABELS, REPEATING COLUMNS The mockup below illustrates a generic class of tables which has a column of row labels with repeating column sets of data (here, Number and Percent) presented alongside. It features spanned headers (Drug1 and Drug2) centered over the detailed column names: Titles Drug 1 Drug 2 Number Percent Number Percent

Cotherapy

ACE inhibitor xxx xx.x% xxx xx.x% Beta-blocker Diuretic . . . NSAID _____________________________________________ Footnotes: This class of tables could also include mocks that have a single set of columns (e.g., N, Mean, Std Dev, Min, Max) with several different output formats. Borders (lines) are used to separate heading and footnotes from the body of the table.

OBJECTIVES
To build a utility that outputs selected items from rectangular SAS datasets to formatted Excel spreadsheets. The utility should be general enough to support a variety of output formats without alteration, should be relatively easy to use and should minimize the amount of manual editing required in Excel.

CATEGORIES, ROW LABELS, REPEATING COLUMNS The second mock is the one encountered most commonly. It adds categories to the column of row labels in the first example. It might group values of a frequency distribution or summary statistics under a variable label. The example below is a fairly common table, the comparison of demographic characteristics for age, ethnicity and gender. The current macro supports one level of nesting, a category and a detailed row label.

NESUG 15

Applications Development

Titles Drug 1 Drug 2 Number Percent Number Percent Age <=65 65-74 65-74 75-84 85-94 >= 95

are a set of PUT commands used to customize the headers and footers and to apply special formatting, such as spanned headers.

DESIGN OPTIONS
There are a half-dozen ways to convert SAS data to an Excel spreadsheet in one or two steps (e.g., export wizard, ODBC, third party DB conversion tools, DDE, HTML output/input, and v8 point and click conversion). Why not just convert the data to Excel and format it in that application, possibly with a VBA macro? The answers were quality, consistency and production cost. Again, the manual editing required was significant and didnt always produce uniform results. Additionally, we think a one-step convert and format approach was more economical and question whether a VBA application could be general enough for the variety of table types required. If fewer tables were needed or a more limited set of output formats desired, it is possible to imagine different, and possibly preferable, designs that involve the simpler types of data conversion and the manual or Excel/VBA macro steps for formatting. Different requirements involve varying tradeoffs between development time and production time.

xxx

xx.x%

xxx

xx.x%

Race/Ethnicity American Indian/Alaskan Native Asian/Pacific Islander Black, not of Hispanic Origin Hispanic White, not of Hispanic Origin Gender Male Female _____________________________________________ Footnotes:

MACRO CALL
COLUMN LABELS ONLY Less often, we encountered requests for tables without any row labels as shown in the example below: Titles Patients Meeting Criteria at Admission Assessment N % xxx xx.x% Patients Meeting Criteria at Annual Assessment N %________ xxx xx.x% The macro call is how the user interacts with the application, akin to an external design specification. A fairly simple method for the user to specify requests for these different display formats was desired. The call should list the variables to be displayed, the output worksheet name, the column widths and formats, the display options and the installation options. %wrtexcel(display=, wksht=, rowlwid=, colwid1-colwid5=, fmt1-fmt5=, [border postions], [display options], [installation options]); where: display = specifies the items to display in the body, wksheet=specifies the name of the output worksheet, rowlwid =width olf the rowlbl column, colwid1 =width of the first repeating column, fmt1=format of the first repeating column. Excel custom formats were used to move numeric data toward the center of the column but leave it right justified, e.g, fmt1=%str(#,##0 ). borders: toprow=, midrow=, botmrow= specify where lines will be drawn rightcol= rightmost column.For line width, number of repetitions display options: has_cat=Y no_rowl=Y footnote=Y rep_col=

___________________________________________ Footnotes: This requirement meant the macro had to be flexible enough to ignore row label formatting when not present and have the repeating columns begin in column 1 or 2.

DECONSTRUCTING A TABLE
Deconstructing a table into its component parts can help design the macro to meet these different objectives. We wanted to keep the call simple but have a flexible utility. The tables have: Titles Headings Body with repeating columns Borders Footnotes

The body of all of these tables could be displayed with a simple PUT command using two options to specify whether or not there are categories or a row label. The borders could be specified at selected row numbers. The titles, headings and footnotes, that varied in number of rows and in special formatting features, presented a challenge. Rather than use numerous macro parameters to pass these calls to the macro, we realized it was easier to code them in user exits, which

(has categories), (no row labels), (execute %footnotes macro for footnotes), number of repeating columns. User needs to specify width of the N and % columns once.

installation options: Excel=location of Excel executable on your system, In_data=default input data set name, maxrows=maximum number of rows. maxcol=maximum number of columns

NESUG 15

Applications Development

/* Example Call #1- Categorical Display */ %wrtexcel(has_cat=Y, footnote=Y, wksht=s100t11, display=%STR(rowlbl '09'x count1 '09'x pcnt1), rowlwid=55, colwid1=20, colwid2=18, fmt1=%str(#,##0 ), fmt2=%str(#,##0.0% ), rep_col=2, toprow=8,midrow=9,botmrow=46, rightcol=3,);

filename ddecmds DDE "excel|system"; /* Format and then save the spreadsheet */ data _null_; length cmnd $ 70; file ddecmds; cmnd=[save.as("c:\'||"%trim(&wksht)"||'.xls")]'; put cmnd; put '[quit()]'; run; This completes writing to the worksheet, saving the data as a .xls application file and quitting the application. Of course, we havent yet accomplished anything more than one of the other file conversion options mentioned above, which could have been done in a few keystrokes or mouse clicks. The basic DDE code could still be useful by itself, however, if there are many files to convert at once.

SAS TO EXCEL- DDE BASICS


SAS sample program DDE-3 shows the basics of how to write data to Excel. Basically, there are three steps: Invoke Excel Write data to the spreadsheet Write formatting commands to the spreadsheet

SAS SYNTAX- FORMATTING EXCEL


Extensions to that last step, formatting the data and wrapping it into a macro call, is where this paper adds to the existing literature. The syntax is hard to find, because it is written in version 4 Excel macro language, and can be tricky to use with SAS macro code because of the double quotes in Excel commands. The different types of formatting options are listed below. Many commands involve selecting a range of rows and columns and then executing a command. Some options will be illustrated with both hard-coded and macro substitution coded selections. PAGE SETUP /* landscape page setup with fit to page */ /* and center horizontally options specified */ put '[Page.Setup(" "," ",0.75,0.75,1,1,False, False,True,False,2,1,True,1,1,False)]'; Parameters are: head, foot, left-, right-, top-, bottom- margins, heading, grid, horizontal center, vertical center, orientation, paper size, scale, page number, page order, cell color FONT CONTROL /* Change font of titles/headings */ put '[select("r4c1:r7c1")]'; put '[Format.Font("Arial",12,False,False,False, False,0)]'; Titles in rows 4-7, column 1 are set to 12pt Arial. These titles will be centered over columns 1-&rightcol later. Parameters are: name of font (such as Arial, Courier, Times), height in points (72 points to an inch), bold, italic, underline, strike, color

INVOKING EXCEL Start Excel and wait before writing data. options noxwait noxsync missing=' ' ; /* Invoke Microsoft Excel. */ X "c:\progra~1\micros~2\office\EXCEL.EXE"; /* /* /* /* /* We must wait for MS Excel to start before we can begin to exchange data. This data step uses the SLEEP function to pause the SAS session for a long enough period, eight seconds here. */ */ */ */ */

data _null_; rc = sleep(8); run; WRITE DATA /* Define a fileref for a range of cells in */ /* an Excel worksheet to transmit the data */ /* using the DDE access method */ FILENAME ddedata DDE "excel|sheet1!r1c1:r&rows.c33" notab lrecl=650; /* Now we write to the Excel worksheet. data _null_; file ddedata ; set trans1 end=eof; put &display ; run; Note the notab option. It's needed so entries with multiple words get written to one column instead of multiple columns. This is why, in Example Call #1 above, the display= parameter contains the tab character 09x (rowlbl 09x count1). The user must specify a column delimiter, which makes the macro less user-friendly. The lrecl=650 FILENAME option lets the user write tables wider than the default. Also note the use of macro variables &rows and &display, illustrating how they will substitute into the code. FORMAT DATA AND SAVE /* /* /* /* Microsoft Excel defines the DDE topic */ "SYSTEM" to allow applications to send*/ commands in order to perform specific */ Excel tasks */ */

COLUMN WIDTHS /* specify widths of the row label */ put '[select("c1")]'; put "[column.width(%trim(&rowlwid))]";

NESUG 15

Applications Development

/* /* /* /*

In a macro for a selection of columns format odd numbered columns to width &colwid1

*/ */ */ */

Parameters are: horizontal align (3=center, 4=right), wrap, vertical align (1=Top, 2=Center, 3=Bottom), orientation (0=Horizontal)

do i=2 to &rightcol; cmnd='[select("c'||put(i,z2.)|| '")]'; put cmnd; if mod(i,2) eq 0 then put "[column.width(%trim(&colwid1))]"; end;

SPANNING CELLS Center titles across the range of columns or display spanned headers between columns for each set of columns. /* Center Titles */ cmnd= '[select("R4C1:R4C'|| "%trim(&rightcol)"||'")]'; put cmnd; put '[Alignment(7,False,3,0)]'; * Center Drug Names between cell pairs; %do j=2 %to 12 %by 2; cmnd= '[select("R08C'|| "%trim(&j):R10c%trim(%eval(&j+1))"||'")]'; put cmnd; put '[Alignment(7,False,3,0)]'; %end; Parameters are: horizontal align (7=Center across selection), wrap, vertical align (1=Top, 2=Center, 3=Bottom), orientation (0=Horizontal) Because of the wide variety of header designs, these commands and the alignment commands above vary considerably from run to run. So they are coded separately in a user exit to %wrtexcel called %othralgn, where the user can customize the tables format. HEADERS AND FOOTNOTES The headers and footnotes are also coded in separate macros with simple PUT commands. This gives the user added flexibility. Needing to use the 09x tab character to skip columns is a bit cumbersome, but not too difficult. For the example below, the header was coded: %macro heading; put '09'x 'Total'; put '09'x 'Total'; put ' Identification Information' 'Number' '09'x 'Percent'; put ' ' ; %mend heading;

COLUMN FORMATS /* hardcoded specification */ put '[select("c3")]'; put "[Format.Number(#,##0 )"; /* In a macro */ /* for a selection of columns */ /* format odd numbered columns */ /* to format &fmt1 */ do i=2 to &rightcol; colnum=put(i,z2.); cmnd='[Select("R1C'||trim(colnum)|| ":R%trim(&rows)C"||trim(colnum)||'")]'; put cmnd; if mod(i,2) eq 0 then cmnd='[Format.Number("'||"%left(&fmt1)"||'")]'; put cmnd; end;

SETTING BORDERS Select a user-specified row (e.g., &toprow) from column 1 to &rightcol and draw the line with the Border command. /* Set Borders */ cmnd='[Select("R'||"%trim(&toprow)C1:R"|| "%trim(&toprow)C%trim(&rightcol)"||'")]'; put cmnd; put '[Border(0,0,0,2,0,0,0,0,0,0,0)]'; Parameters are: outline, left, right, top, bottom, shade, outline-, left-, right-, top-, bottom-colors values 0=none 1=Thin Line, 2=Medium Line, 3=Dashed Line 4=Dotted Line, 5=Thick Line, 6-Double Line, 7=Hairline ALIGNING DATA IN CELL Text data are, by default, left aligned and numeric data are right aligned. Use the following to center or right-align text. /* Center Justify Headings and Wrap Text */ put '[select("R09C2:R10C9")]'; put '[Alignment(3,True,2,0)]'; /* Justify Right Header, Dont Wrap */ put '[select("R09C2:R10C9")]'; put '[Alignment(4,False,2,0)]'; /* Right Align in Macro */ cmnd='[select("R1C'||"%trim(&rightcol):R3C"|| "%trim(&rightcol)"||'")]'; put cmnd; put '[Alignment(4,False,2,0)]'; Note the substitution selects the top three rows and the right-most column and right justifies text. This is shown in Example Table #1 which follows.

'09'x

The second line with Total will be spanned between two columns. The footnote was coded: %macro footnote; put ' '; put 'Note: Frequency counts may not add to total and percentages may not add to 100'; put ' due to incomplete information for a few residents.'; %mend footnote; REMAINING MANUAL STEPS We still havent figured out how to do a few formatting steps, so they are still done manually: -superscript a number in a heading or beginning of a footnote. -wrapping data in a spanned set of cells.

NESUG 15

Applications Development

EXAMPLE TABLE # 1 The figure above is an Excel print preview of a spreadsheet created by %wrtexcel. Notice the aligned header in the first three rows, centered titles, spanned headers, borders and category labels.

features. Otherwise, DDE features are little more than a file conversion technique and there are a number of easier, one-step data conversion methods available. Our conversion to a UNIX server platform with a PC front-end presents some challenges for producing displays in Excel. Using SAS for Windows and SAS/CONNECT should make it possible to achieve the same DDE result.

BEYOND- ADAPTING TO CHANGE


Our site is moving to a UNIX server with the new thin-client SAS front-end called Enterprise Guide. We will also be moving from SAS v6.12 to SAS v8.2, with its new options afforded us with the ODS (output delivery system). This is a change from our SAS for Windows environment with data stored on an NT server. How can we transfer the capability to easily write SAS Output to Excel? It's going to require additional software or different procedures. Here are our observations so far: 1) Enterprise Guide doesnt support DDE or X (escape to server) commands. It does feature a nice point and click feature to convert UNIX based SAS data to PC based .XLS files but without the formatting we seek. 2) UNIX server doesnt support DDE, either. 3) Among the new output options afforded by ODS in SAS v 8.x (.rtf, ASCII, HTML, and PDF), HTML is promising and can be imported directly into Excel. Many manual-formatting steps will remain. 4) SAS technical support tells us that SAS for Windows with SAS/CONNECT will allow us to run a task on the UNIX server and then run %wrtexcl on the PC server. We are testing this approach. 5) The alternatives beyond DDE would be a compromise, so we hope the approach SAS technical support has proposed will work with the only additional cost being SAS for Windows licenses for the users needing %wrtexcel.

REFERENCES
SAS Institute Inc., SAS Sample Library- DDE Example 3: Sending Commands to Excel via DDE, 2000. Microsoft Corporation, Microsoft Excel: Function Reference Version 4, 1992.

CONTACT INFORMATION
Please contact the authors with your comments, questions or requests for a copy of the macro at: Lawrence Helbers Omnicare Clinical Research 630 Allendale Road King of Prussia, PA 19406 Work Phone: 484-679-2421 Fax: 484-679-2509 Email: Larry.Helbers@omnicarecr.com Alex Vinokurov Omnicare Clinical Research 630 Allendale Road King of Prussia, PA 19406 Work Phone: 484-679-3148 Fax: 484-679-2509 Email: Alexander.Vinokurov@omnicarecr.com SAS is a registered trademark or trademark of the SAS Institute Inc., Cary NC in the USA and other countries. Other brand and product names are registered trademarks or trademarks of their respective companies.

CONCLUSION
SASs flexibility and power allowed us to develop a macro that creates displays in a wide variety of table layouts in neatly formatted Excel spreadsheets. The macro has saved time, making manual editing largely unnecessary, and has improved the quality/consistency of our output. We hope this paper will help others master the syntax necessary to use Excels formatting

Das könnte Ihnen auch gefallen