How can I avoid having a word broken instead of the breaking on the white space before it?
I thought about writing a PRXCHANGE function to substitute the first space before the non-space characters that exceed a certain length but that would probably challenge me and it would like have to be in a loop, since my Regex skills are functions, not superb 🙂
I would appreciate any suggestions or references.
Thank you,
Kevin
PS I note that the documentation specifies:
Restriction | This option only affects the LISTING output. It has no affect on other ODS output. |
Hi:
I'm just not sure why you are worrying so much about the length or the wrapping. I would not bother. If INDENT= is not what you want and you DO want the wrapped text to be indented, then the LEFTMARGIN= attribute does that, as shown below.
Before you go into template land, you can experiment with CELLPADDING values and fonts in PROC REPORT and THEN, after you find the values that give you the report you want, you can move them to a style template. The TABLE element will apply to the PROC REPORT table. I like to start with the PROC REPORT attributes in the PROC REPORT code, so I can experiment to see which values I want to use and then, after that I move into template land.
Here's my paper about tiptoeing through the templates: https://support.sas.com/resources/papers/proceedings09/227-2009.pdf and the one on style templates: https://support.sas.com/resources/papers/proceedings10/033-2010.pdf .
And, here's an example of wrapping long text along with using INDENT or LEFTMARGIN:
I did turn on the border lines and interior table lines in the long text example so you could be assured that the INDENT and LEFTMARGIN were working as designed.
I find that ODS and SAS do a good job of not splitting words at a bad place such that I do not need to over-control the text strings by inserting my own line breaks. The only time I really insert line breaks is when I want to "stack" information in one cell and control exactly where the line break will occur, such as:
data newclass;
set sashelp.class(obs=2);
length newvar1 newvar2 $200;
newvar1 = cat('Name: ',name,'~{newline 1}','Sex: ',sex,'~{newline 1}','Age: ',put(age,2.0));
newvar2 = cat('Height:',put(height,5.1),'~{newline 1}','Weight: ',put(weight,5.1));
run;
ods escapechar='~';
proc report data=newclass;
column newvar1 newvar2;
run;
Perhaps I am missing the big picture, but you're not showing all your code and all your data, but based on what you've indicated so far, I don't think you need to go down the REGEX road or insert your own NEWLINE characters.
cynthia
Kevin,
Is there a chance that you have "asis=on" within your style?
Art, CEO, AnalystFinder.com
Hi:
Are you using INDENT= to do your indent or did you pad the sentence with blanks. I found that INDENT= worked for me. I tried fiddling with the WIDTH= value quite a bit and could not make it split "the" or "completed" as you experienced.
Also not sure why you included the doc reference on FLOW -- it is a LISTING only option and irrelevant to ODS PDF and other ODS destinations (sort of like HEADLINE, HEADSKIP, SPACING and SKIP -- just not used by any destination except LISTING).
cynthia
Cynthia,
I included the documentation on Flow to let reader know that I was aware of this option and that, as you observed, is for the LISTING destination.
I should have given more details: Times New Roman, 10 pt, with
class table from output
/ frame = hsides
rules = groups
cellpadding = 2.0pt
cellspacing = 0.5pt
borderwidth = 1.0pt
background = color_list( "BGT" )
;
I am still weak on TEMPLATEs, so I am not sure if the above applies to report. It is legacy code that I obtained and 2.0 pt padding seems undesirable.
I padded the variable value with blank spaces (PDF and RTF destinations). I found that when wrapping occurs, then the INDENT does not apply to the subsequent lines (as you show below). Instead, I manually inserted:
if row_1 = " Subject had a clinically significant protocol deviation during the induction phase"
then row_1 = " Subject had a clinically significant protocol deviation during^n the induction phase" ;
Note that my ODS ESCAPECHAR = "^" and three spaces follow "^n". The issue is that we might have listings of hundreds of pages. I stumbled onto http://www.pharmasug.org/proceedings/2012/CC/PharmaSUG-2012-CC22.pdf
"A Macro to Indent and Hyphenate Lengthy Text in PROC REPORT" by Stanley Yuen
Note that Regex can get us pretty far:
12528 data _null_ ;
12529 length x $ 200 ;
12530 x = " three little pigs" ;
12531 x = prxchange( "s/(.*)(?:\s+)([\S]*)$/$1^n%sysfunc(repeat( %str( ) , 2 ))$2/o" , 1 , trim( x )) ;
12532 put x $char40. ;
12533 run ;
three little^n pigs
(With some flexibility, with the number of spaces ready to be replaced by a macro variable, complicating the code.)
Bummer, as you observed in a previous post, we'd need to use   since we are in HTML land so the leading three spaces are gone...
The macro would to break on spaces, or if we allow, in words (using a hyphen), would not be that complicated.
The big issue is length. I spent some time reading about fonts because some asked me to predict how many characters would fit in a given column/table. Fascinating, if you can believe it, but I like books and did not mind reading about printing presses (carrying over from my childhood when I found an old newpaper in New Hampshire that had those "funny" s's that look similar to f's with a base and no line in the middle. The only thing that I can think of at the moment is to use the least narrow and the widest (M?) characters to find a conservative length, but we have not guarantee other bytes, like symbols will not appear in the value.
Thank you,
Kevin
Hi:
I'm just not sure why you are worrying so much about the length or the wrapping. I would not bother. If INDENT= is not what you want and you DO want the wrapped text to be indented, then the LEFTMARGIN= attribute does that, as shown below.
Before you go into template land, you can experiment with CELLPADDING values and fonts in PROC REPORT and THEN, after you find the values that give you the report you want, you can move them to a style template. The TABLE element will apply to the PROC REPORT table. I like to start with the PROC REPORT attributes in the PROC REPORT code, so I can experiment to see which values I want to use and then, after that I move into template land.
Here's my paper about tiptoeing through the templates: https://support.sas.com/resources/papers/proceedings09/227-2009.pdf and the one on style templates: https://support.sas.com/resources/papers/proceedings10/033-2010.pdf .
And, here's an example of wrapping long text along with using INDENT or LEFTMARGIN:
I did turn on the border lines and interior table lines in the long text example so you could be assured that the INDENT and LEFTMARGIN were working as designed.
I find that ODS and SAS do a good job of not splitting words at a bad place such that I do not need to over-control the text strings by inserting my own line breaks. The only time I really insert line breaks is when I want to "stack" information in one cell and control exactly where the line break will occur, such as:
data newclass;
set sashelp.class(obs=2);
length newvar1 newvar2 $200;
newvar1 = cat('Name: ',name,'~{newline 1}','Sex: ',sex,'~{newline 1}','Age: ',put(age,2.0));
newvar2 = cat('Height:',put(height,5.1),'~{newline 1}','Weight: ',put(weight,5.1));
run;
ods escapechar='~';
proc report data=newclass;
column newvar1 newvar2;
run;
Perhaps I am missing the big picture, but you're not showing all your code and all your data, but based on what you've indicated so far, I don't think you need to go down the REGEX road or insert your own NEWLINE characters.
cynthia
Are you ready for the spotlight? We're accepting content ideas for SAS Innovate 2025 to be held May 6-9 in Orlando, FL. The call is open until September 16. Read more here about why you should contribute and what is in it for you!
Learn how use the CAT functions in SAS to join values from multiple variables into a single value.
Find more tutorials on the SAS Users YouTube channel.
Select SAS Training centers are offering in-person courses. View upcoming courses for: