Text Wrapping with Indentation for RTF Reports

Similar documents
Indenting with Style

Customized Flowcharts Using SAS Annotation Abhinav Srivastva, PaxVax Inc., Redwood City, CA

Regaining Some Control Over ODS RTF Pagination When Using Proc Report Gary E. Moore, Moore Computing Services, Inc., Little Rock, Arkansas

This paper describes a report layout for reporting adverse events by study consumption pattern and explains its programming aspects.

Presentation Quality Bulleted Lists Using ODS in SAS 9.2. Karl M. Kilgore, PhD, Cetus Group, LLC, Timonium, MD

A SAS Macro Utility to Modify and Validate RTF Outputs for Regional Analyses Jagan Mohan Achi, PPD, Austin, TX Joshua N. Winters, PPD, Rochester, NY

PharmaSUG China. Systematically Reordering Axis Major Tick Values in SAS Graph Brian Shen, PPDI, ShangHai

ODS/RTF Pagination Revisit

Summary Table for Displaying Results of a Logistic Regression Analysis

IT S THE LINES PER PAGE THAT COUNTS Jonathan Squire, C2RA, Cambridge, MA Johnny Tai, Comsys, Portage, MI

Formatting Highly Detailed Reports: Eye-Friendly, Insight-Facilitating

PharmaSUG China Paper 059

PharmaSUG Paper PO10

BreakOnWord: A Macro for Partitioning Long Text Strings at Natural Breaks Richard Addy, Rho, Chapel Hill, NC Charity Quick, Rho, Chapel Hill, NC

A Fully Automated Approach to Concatenate RTF outputs and Create TOC Zhiping Yan, Covance, Beijing, China Lugang Xie, Merck, Princeton, US

An Efficient Tool for Clinical Data Check

SAS 9 Programming Enhancements Marje Fecht, Prowerk Consulting Ltd Mississauga, Ontario, Canada

FILLPATTERNS in SGPLOT Graphs Pankhil Shah, PPD, Morrisville, NC

My Reporting Requires a Full Staff Help!

Streamline Table Lookup by Embedding HASH in FCMP Qing Liu, Eli Lilly & Company, Shanghai, China

TLF Management Tools: SAS programs to help in managing large number of TLFs. Eduard Joseph Siquioco, PPD, Manila, Philippines

Run your reports through that last loop to standardize the presentation attributes

Create a Format from a SAS Data Set Ruth Marisol Rivera, i3 Statprobe, Mexico City, Mexico

PharmaSUG 2013 CC26 Automating the Labeling of X- Axis Sanjiv Ramalingam, Vertex Pharmaceuticals, Inc., Cambridge, MA

ABSTRACT INTRODUCTION TRICK 1: CHOOSE THE BEST METHOD TO CREATE MACRO VARIABLES

Reproducibly Random Values William Garner, Gilead Sciences, Inc., Foster City, CA Ting Bai, Gilead Sciences, Inc., Foster City, CA

Using GSUBMIT command to customize the interface in SAS Xin Wang, Fountain Medical Technology Co., ltd, Nanjing, China

footnote1 height=8pt j=l "(Rev. &sysdate)" j=c "{\b\ Page}{\field{\*\fldinst {\b\i PAGE}}}";

Your Own SAS Macros Are as Powerful as You Are Ingenious

Cover the Basics, Tool for structuring data checking with SAS Ole Zester, Novo Nordisk, Denmark

PROBLEM FORMULATION, PROPOSED METHOD AND DETAILED DESCRIPTION

An Efficient Method to Create Titles for Multiple Clinical Reports Using Proc Format within A Do Loop Youying Yu, PharmaNet/i3, West Chester, Ohio

Validation Summary using SYSINFO

When Powerful SAS Meets PowerShell TM

ABSTRACT INTRODUCTION MACRO. Paper RF

A SAS Macro to Create Validation Summary of Dataset Report

Paper SIB-096. Richard A. DeVenezia, Independent Consultant, Remsen, NY

ODS DOCUMENT, a practical example. Ruurd Bennink, OCS Consulting B.V., s-hertogenbosch, the Netherlands

A Format to Make the _TYPE_ Field of PROC MEANS Easier to Interpret Matt Pettis, Thomson West, Eagan, MN

TLFs: Replaying Rather than Appending William Coar, Axio Research, Seattle, WA

ODS for PRINT, REPORT and TABULATE

INTRODUCTION TO SAS HOW SAS WORKS READING RAW DATA INTO SAS

A SAS Macro to Generate Caterpillar Plots. Guochen Song, i3 Statprobe, Cary, NC

CC13 An Automatic Process to Compare Files. Simon Lin, Merck & Co., Inc., Rahway, NJ Huei-Ling Chen, Merck & Co., Inc., Rahway, NJ

Using PROC REPORT to Cross-Tabulate Multiple Response Items Patrick Thornton, SRI International, Menlo Park, CA

Combining TLFs into a Single File Deliverable William Coar, Axio Research, Seattle, WA

PharmaSUG Paper AD03

Paper PO07. %RiTEN. Duong Tran, Independent Consultant, London, Great Britain

Breaking up (Axes) Isn t Hard to Do: An Updated Macro for Choosing Axis Breaks

PharmaSUG Paper TT11

To conceptualize the process, the table below shows the highly correlated covariates in descending order of their R statistic.

Useful Tips When Deploying SAS Code in a Production Environment

Making an RTF file Out of a Text File, With SAS Paper CC13

This Too Shall Pass: Passing Simple and Complex Parameters In and Out of Macros

SAS Programming Techniques for Manipulating Metadata on the Database Level Chris Speck, PAREXEL International, Durham, NC

Give me EVERYTHING! A macro to combine the CONTENTS procedure output and formats. Lynn Mullins, PPD, Cincinnati, Ohio

Getting it Done with PROC TABULATE

An Alternate Way to Create the Standard SDTM Domains

ABSTRACT MORE THAN SYNTAX ORGANIZE YOUR WORK THE SAS ENTERPRISE GUIDE PROJECT. Paper 50-30

Automated Macros to Extract Data from the National (Nationwide) Inpatient Sample (NIS)

Quick and Efficient Way to Check the Transferred Data Divyaja Padamati, Eliassen Group Inc., North Carolina.

ODS TAGSETS - a Powerful Reporting Method

A Mass Symphony: Directing the Program Logs, Lists, and Outputs

Producing Summary Tables in SAS Enterprise Guide

Java Programming Style Guide

Automated Checking Of Multiple Files Kathyayini Tappeta, Percept Pharma Services, Bridgewater, NJ

A Macro that can Search and Replace String in your SAS Programs

PharmaSUG Paper CC02

PharmaSUG Paper TT10 Creating a Customized Graph for Adverse Event Incidence and Duration Sanjiv Ramalingam, Octagon Research Solutions Inc.

A Tool to Compare Different Data Transfers Jun Wang, FMD K&L, Inc., Nanjing, China

%MISSING: A SAS Macro to Report Missing Value Percentages for a Multi-Year Multi-File Information System

Troy Martin Hughes ABSTRACT INTRODUCTION

Making a SYLK file from SAS data. Another way to Excel using SAS

Post-Processing.LST files to get what you want

QUERIES BY ODS BEGINNERS. Varsha C. Shah, Dept. of Biostatistics, UNC-CH, Chapel Hill, NC

A Linux Shell Script to Automatically Compare Results of Statistical Analyses

A Macro to replace PROC REPORT!?

Get into the Groove with %SYSFUNC: Generalizing SAS Macros with Conditionally Executed Code

PharmaSUG China 2018 Paper AD-62

SAS Display Manager Windows. For Windows

C++ Programming Style Guide

How to validate clinical data more efficiently with SAS Clinical Standards Toolkit

A Quick and Gentle Introduction to PROC SQL

PharmaSUG China. model to include all potential prognostic factors and exploratory variables, 2) select covariates which are significant at

PharmaSUG Paper CC11

Anyone Can Learn PROC TABULATE, v2.0

Data Edit-checks Integration using ODS Tagset Niraj J. Pandya, Element Technologies Inc., NJ Vinodh Paida, Impressive Systems Inc.

Easing into Data Exploration, Reporting, and Analytics Using SAS Enterprise Guide

Macro Quoting: Which Function Should We Use? Pengfei Guo, MSD R&D (China) Co., Ltd., Shanghai, China

Building a Template from the Ground Up with GTL

Data Quality Review for Missing Values and Outliers

Taming a Spreadsheet Importation Monster

Quality Control of Clinical Data Listings with Proc Compare

PharmaSUG China Paper 70

%Addval: A SAS Macro Which Completes the Cartesian Product of Dataset Observations for All Values of a Selected Set of Variables

Using SAS 9.4M5 and the Varchar Data Type to Manage Text Strings Exceeding 32kb

An Automation Procedure for Oracle Data Extraction and Insertion

Tips for Mastering Relational Databases Using SAS/ACCESS

The Path To Treatment Pathways Tracee Vinson-Sorrentino, IMS Health, Plymouth Meeting, PA

Applications Development. Paper 38-28

Transcription:

ABSTRACT Text Wrapping with Indentation for RTF Reports Abhinav Srivastva, Gilead Sciences Inc., Foster City, CA It is often desired to display long text in a report field in a way to avoid splitting in an unusual manner when rendered with reporting procedures in SAS. Sometimes, the field can be a combination of several other fields or variables, in which case, the resultant text field needs to be well formatted for readability to the consumer. The paper presents a brief overview of common text wrapping and indentation options for RTF outputs and will incorporate one of the methods in building a SAS macro capable of text wrapping and indentation on one or more text fields. INTRODUCTION For indentation and wrapping in RTF, several options exist and below Table is a summary of some of them: Indentation Methods RTF Control Words: \li and \fi Style overrides: indent = xx, leftmargin=xx Usage String = Some long text to be formatted With \li250 : string = Some long text to be formatted With \fi-250\li250 : string = Some long text to be formatted' Combination of \li and \fi can produce hanging text as above. (\li=left indent, \fi=first line indent) style = [indent = xx] style = [leftmargin=xx] Pretext in PROC REPORT Pretext = [ {empty string or RTF control words} ] Styling with ASIS=ON string = Some long text to be formatted Table 1: Indentation methods for RTF Spaces are added beforehand in the data so that ASIS=ON in PROC REPORT will honor it. For splitting long text across lines, there are several options too; either explicitly specifying certain characters in the data such as ^n, ^{newline 1}, RTF control words like \line (where ^= escape character) or through styling column width as <cellwidth=xx>. While all of these would work fine when dealing with a single text field but when multiple fields or columns are combined and reported as a single text field, it could become quite challenging in enabling readability to the end user. With that in perspective, the %text_wrap macro (discussed below) handles them smoothly using a white space character w and a new line character n, eg. ^w and ^n, and formats them as desired. TEXT WRAPPING EXAMPLES Let s assume there is a Variable A in the dataset which has long text and needs to be reported with a set column width of 20% in the report. The following code will restrict to 20% as desired: display Variable_A / style(column)=[cellwidth=20%]; Data (Variable A) Report Column (Variable A) CCC DDDDDD EEEEE FFFFFFFFF CCC DDDDDD EEEEE FFFFFFFFF Table 2: REPORT Procedure <cellwidth=> style option 1

The output can be enhanced with some indentation when text flows over to the next line or every subsequent line thereafter with RTF control words fi-xx\lixx where xx=# of twips (1 twip= 1/20 th of a point, or 1440 twips= 1 inch). display Variable_A / style(column)=[cellwidth=20% protectspecialchars=off pretext= \pnhang\fi-250\li250 ]; Data (Variable A) Report Column (Variable A) CCC DDDDDD EEEEE FFFFFFFFF CCC DDDDDD EEEEE FFFFFFFFF Table 3: REPORT Procedure with RTF control words Next, let s consider a case when multiple text columns are combined into one (using ^n or new line character) to be reported as a single report column as demonstrated below: data B; set A; New_Var = catx( ^n, Variable_A, Variable_B, Variable_C); run; ods escapechar= ^ ;... display New_Var / style(column)=[cellwidth=20%]; PPPPPPP QQQQQ RRRRR Table 4: Combing multiple columns into one PPPPPPP QQQQQ RRRRR An immediate improvement, just like the case with single column (Table 3), can be made in the resultant report column is with the indentation of text for each variable so as to clearly distinguish them in the report. For new line and indentation ^n^w^w string as delimiter in CATX function is used below to add two leading spaces for each variable. data B; set A; New_Var = catx( ^n^w^w, Variable_A, Variable_B, Variable_C); run; PPPPPPP QQQQQ RRRRR Table 5: Combining multiple columns into one with indentation PPPPPPP QQQQQ RRRRR 2

As observed in the resultant report column (New_Var) from the above display (Table 5), Variables B and C begin with two leading spaces as expected, but the text wrapping isn t quite accurate as the text always starts at the first position in the column when it does not fit completely as per the pre-specified column width. So the text ZZZZZZZZ coming from will start at the first position in the column making it not appealing to the user. The macro discussed below handles this situation and others that could potentially arise in the data. TEXT WRAP MACRO Basic usage of the Text Wrap macro is as below: %macro text_wrap (dsn =, /* Name of the Input dataset */ invars =, /* Input Variable(s), separate with space, example: VarA VarB VarC */ outvar =, /* Name of the resultant variable in the report */ width = 30, /* Desired # characters to fit per line in outvar, default=30 */ ind = 1, /* Indent spaces to add, default=1 */ esc = ^, /* Escape character, default=^ */ countvar = c ); /* Variable to display total # lines consumed by outvar, useful when deciding # lines per page */ The resultant column from Table 5 can be formatted with %text_wrap macro to improvise on wrapping and indentation. In the resultant column, the macro will indent every variable in the same proportion, i.e. if <ind= > parameter in the macro call is 2 then Variable B text will be indented with 2 spaces relative to Variable A; text will be indented with 2 spaces relative to Variable B for a total of 4 indents from the first column position (or Variable A). Also, the text from each variable will wrap corresponding to its starting position and not flow from the beginning of the column as happened in Table 5. PPPPPPP QQQQQ RRRRR PPPPPPP QQQQQ RRRRR Table 6: Revised result with Text Wrap Macro Sometimes, the data can have missing values for one or more variables; in that case %text_wrap macro will hold # spaces as a way to indicate a missing value. Consider the case when Variable B has a missing value, then with <indent=2> parameter the resultant column will have text from indented 4 spaces assuming 2 indents for Variable B text which happens to be missing, and this indent pattern should indicate the user of a missing value in the data for Variable B. Table 7: Text Wrap Macro result with missing data Please refer to Appendix for complete SAS code of the Text Wrap Macro. 3

CONCLUSION SAS provide a number of ways to format text and this paper leverages on one of them to build a macro capable of dealing with RTF destination. The summary table (Table 1) should be a good starting point to explore different methods. Also, the readers are encouraged to try different methods against different ODS destinations to see the interaction and find a solution for their individual needs. REFERENCES SAS support, Sample 42377: Create a hanging indent in the ODS RTF destination, http://support.sas.com/kb/42/377.html Zender, Cynthia. Practically Perfect Presentations Using ODS and PROC REPORT. PharmaSUG 2007. Hands-On- Workshop. Parsons, S. Lori. 2007. Enhancing RTF Output with RTF Control Words and In-Line Formatting, Paper 151-2007. SAS Global Forum 2007. Matthews, Carol & Kalchenko, Elena, Pretty Please?! Making RTF Output Pretty with SAS, PharmaSUG 2013 Paper IB08. ACKNOWLEDGMENTS I would like to thank Ms. Asha Srivastva for the encouragement and review of this paper. CONTACT INFORMATION Your comments and questions are valued and encouraged. Contact the author at: Name: Abhinav Srivastva Enterprise: Gilead Science Inc Address: 333 Lakeside Dr. City, State ZIP: Foster City, CA 94404 Work Phone: (650) 389-8778 E-mail: Abhinav.Srivastva@gilead.com 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 are trademarks of their respective companies. 4

APPENDIX %macro text_wrap (dsn =, invars =, outvar = newvar, width = 30, ind = 1, esc = ^, countvar = c ); %global levels; /* Basic parameters check */ %if &dsn. = ' ' %then %do; %put No Dataset provided ; %if &invars. = ' ' %then %do; %put No Input Variables Provided ; %if &ind. < 1 %then %do; %put Indent parameter has to be > 1; /* Check the existence of variables in the given dataset */ %let dsid = %sysfunc(open(&dsn.)); %if (&dsid) %then %do; %let k=1; %let comp_str = &invars; %do %while(%scan(&comp_str.,&k.,%str( )) ne %str( )); %let var2comp = %scan(&comp_str.,&k.,%str( )); %if %sysfunc(varnum(&dsid.,&var2comp.)) %then %put Valid Variable(s) entered; %put!!! Variable &var2comp. not found.!!!; %let k = %eval(&k.+1); %let rc = %sysfunc(close(&dsid)); %let levels=%eval(&k.-1); /* Process each variable and format as needed (wrap + Indent) */; data &dsn. (drop = len nwords count word &outvar.: c:); set &dsn.; %do i=1 %to &levels.; 5

%let var&i.= %scan(&invars.,&i.,%str( )); %let indent&i.= %eval(&i. * &ind. - &ind.); length &outvar&i. $ 1000 &outvar $ 5000 word $200; *- please adjust if needed; &countvar&i. = 1; &outvar&i. = ''; len=0; count=0; word=''; nwords = countw(&&var&i., ' '); if nwords>0 then do; * count loop; do count = 1 to nwords; word = scan(&&var&i., count, ' '); if len + 1 + length(word) > &width. then do; &countvar&i. +1; * append word and if length > width then insert a new line *; %if &i.=1 %then %do; %if &i. = &levels. %then %do; &outvar&i. = strip( &outvar&i. ) "&esc.n" repeat(%str("&esc.w"),%eval(&ind.-1 )) word; &outvar&i. = strip( &outvar&i. ) "&esc.n" word; &outvar&i. = strip( &outvar&i. ) "&esc.n" repeat(%str("&esc.w"),%eval(&&indent&i.-1)) word; len = length(word); else do; * if length < width then we do not need to append *; &outvar&i. = strip( &outvar&i. ) ' ' word; len = len + length(word) + 1; else do; &countvar&i. = 0; %if &i.=1 %then %do; &outvar&i. = left( &outvar&i. ); if &outvar&i. ^= ' ' then &outvar&i. = repeat(%str("&esc.w"),%eval(&&indent&i.-1)) left( &outvar&i. ); &outvar = catx("&esc.n",of &outvar.:); &countvar = sum(of &countvar.:); run; %exit: %m 6