BookmarkSubscribeRSS Feed
KaySca81
Calcite | Level 5

Hi,

I have a problem with drawing some horizontal lines in tables produced by proc report. The table looks like that:

Column1Column2Column3
Section 1xxx xxx
Section 1xxxxxx
Section 1xxxxxx
Section 2xxx xxx
Section 2xxxxxx
Section 3xxx xxx

I want to have a thicker line (underline) after each section (see column1). I tried "break after ... /OL" in proc report but it's only working with listing, not with RTF output. That statement is ignored when using ODS RTF. I also tried to insert another row with 0pt size (computer after and line statement in proc report) but a font size lower than 6pt is not allowed. Last, I wrote RTF code words in the SAS data set, e.g. -  Column1 = "^{style [bordertopwidth=2pt]}"||Column1;  - and I do that for each column. This solution is working but there is one bug - there is a leading blank in each cell (I tried to demonstrate that in Column3 - if a new section starts, i.e. if RTF code words are implemented in the variables, there will be a leading blank). I cannot see the blank in the SAS dataset but only in the output - I tried SAS character functions, e.g. "strip" but it did not change anything.

If someone has an idea - how to avoid/delete the leading blanks or better, if someone has a better idea than writing RTF code words in SAS datasets, please let me know!

Thanks for help!!!

5 REPLIES 5
Cynthia_sas
SAS Super FREQ


Hi:

  Can you share your PROC REPORT code? The entire code -- including ODS RTF statements and your PROC REPORT statements would be most useful.

Thanks,

cynthia

KaySca81
Calcite | Level 5


Hi, here an example SAS code:

ods escapechar='^';

data lines;

input section column1$ column2$ column3$ column4$ column5$;

cards;

1 A B C D E

1 A B C D E

1 A B C D E

2 B C D E F

2 B C D E F

3 C D E F G

3 C D E F G

;

run;

*add RTF code words to data set;

data lines;

length column1-column5 $100.;

set lines;

by section;

if first.section then do;

column1 = "^{style [bordertopwidth=2pt]}"||column1;

column2 = "^{style [bordertopwidth=2pt]}"||column2;

column3 = "^{style [bordertopwidth=2pt]}"||column3;

column4 = "^{style [bordertopwidth=2pt]}"||column4;

column5 = "^{style [bordertopwidth=2pt]}"||column5;

end;

run;

proc template;

define style MYSTYLE;

class Table /

frame = box

rules = none

borderbottomwidth=2pt

bordertopwidth=2pt

borderrightwidth=2pt

borderleftwidth=2pt

;

end;

run;

ods listing close;

ods rtf file = "C:/example_lines.rtf" style=MYSTYLE;

proc report data=lines NOWINDOWS BOX STYLE(header)=[borderrightwidth=2pt background=white];

column section column1 column2 column3 column4 column5;

define section / order order=data noprint;

define column1 / style(column)=[borderrightwidth=2pt]

                         style(header)=[borderrightwidth=2pt borderbottomwidth=2pt];

define column2 / style(column)=[borderrightwidth=1pt]

                         style(header)=[borderrightwidth=1pt borderbottomwidth=2pt];

define column3 / style(column)=[borderrightwidth=2pt]

                         style(header)=[borderrightwidth=2pt borderbottomwidth=2pt];

define column4 / style(column)=[borderrightwidth=1pt]

                         style(header)=[borderrightwidth=1pt borderbottomwidth=2pt];

define column5 / style(column)=[borderrightwidth=2pt]

                         style(header)=[borderrightwidth=2pt borderbottomwidth=2pt];

;

quit;

ods rtf close;

>> If someone has an idea - how to avoid/delete the leading blanks or better, if someone has a better idea than writing RTF code words in SAS >> datasets, please let me know!

Thanks.

Cynthia_sas
SAS Super FREQ


Hi:

  I think you are working too hard. I don't think you need a custom style template. You can add a blank line at the break and then turn the border style of the blank line to be what you want. I think that may be easier than attaching ODS STYLE overrides to each variable value, as you show.

  Here's the thing. RTF control strings -- real RTF control strings start with \ -- like \line, \b, \i, etc. What you are putting into your variable values are "pure" ODS -- ODS ESCAPECHAR style = overrides. And, I don't think you need them.

  I am teaching this week and not able to run new code. I believe your leading space will go away once you no longer embed the style override on each variable value. I would recommend starting from the JOURNAL style, adding the COLUMN lines and then putting a line at the break. After class, I can search for an example that might help. Otherwise, you could fiddle around with:

ods rtf ... style=journal; (instead of your style)

proc report ....

       style(report)={frame=box rules=cols};

and then something like:

compute after section / style={bordertopcolor=black borderbottomcolor=black height=1px cellpadding=0};

  line ' ';

endcomp;


Sorry I can't be of more help, but maybe that will help you get pointed in a different direction.

cynthia

BTW, some options like BOX, FLOW, SKIP, etc are LISTING-only options and are ignored by ODS RTF, PDF and HTML.

Cynthia_sas
SAS Super FREQ

Hi:

  OK...finally had some time to create a set of examples. See attached screenshot that shows all 6 outputs side by side, created with code shown below. Note that each numbered title corresponds to a different method. None of my methods use a custom style template. All my outputs, however, start with using the JOURNAL style and go from there. In #4, I did use "pure" RTF control strings (\brdrt\brdrs) so you could see the difference. What you had in your original code was ODS ESCAPECHAR style overrides - -which look a bit different.

You can use style overrides on the break between sections, but generally, there has to be something you put onto the report at the break. I use the LINE statement with a ' ' (quote space quote) to write out a blank line. As you can see, even though I specify an extremely small height for the blank, there is a limit to how small RTF will let you specify a height value and whether Word will use the value "unadjusted". There are probably "pure" RTF methods that would alter the cell height and/or put a single borderline under the last obs of a group, but I'm not great with RTF control strings.

cynthia

*** The code;

data lines;
input section column1$ column2$ column3$ column4$ column5$;
return;
cards;
1 A B C D E
1 A B C D E
1 A B C D E
2 B C D E F
2 B C D E F
3 C D E F G
3 C D E F G
;
run;
    
ods listing close;
ods rtf file = "C:\temp\example_lines.rtf" style=journal;
    
proc report data=lines NOWINDOWS
     STYLE(report)=[frame=box rules=cols]
     style(header)={borderbottomwidth=2pt borderbottomcolor=black};
title '1) Using color as a divider';
column section column1 column2 column3 column4 column5;
define section / order order=data noprint;
define column1 / "Column 1";
define column2 /  "Column 2";
define column3 /  "Column 3";
define column4 /  "Column 4";
define column5 /  "Column 5";
compute after section /
        style={height=1px background=cx999999 cellpadding=0};
  line ' ';
endcomp;
run;
     
proc report data=lines NOWINDOWS
     STYLE(report)=[frame=box rules=cols]
     style(header)={borderbottomwidth=2pt borderbottomcolor=black};
title '2) Using blank (white) line as divider';
column section column1 column2 column3 column4 column5;
define section / order order=data noprint;
define column1 / "Column 1";
define column2 /  "Column 2";
define column3 /  "Column 3";
define column4 /  "Column 4";
define column5 /  "Column 5";
compute after section  /
        style={height=1px cellpadding=0};
  line ' ';
endcomp;
run;
     
proc report data=lines NOWINDOWS
     STYLE(report)=[frame=box rules=cols]
     style(header)={borderbottomwidth=2pt borderbottomcolor=black};
title '3) Using border lines as a divider';
column section column1 column2 column3 column4 column5;
define section / order order=data noprint;
define column1 / "Column 1";
define column2 /  "Column 2";
define column3 /  "Column 3";
define column4 /  "Column 4";
define column5 /  "Column 5";
compute after section /
        style={height=1px bordertopcolor=black borderbottomcolor=black cellpadding=0
               bordertopstyle=solid borderbottomstyle=solid
               bordertopwidth=2pt borderbottomwidth=2pt};
  line ' ';
endcomp;
run;
     
proc report data=lines NOWINDOWS
     STYLE(report)=[frame=box rules=cols]
     style(header)={borderbottomwidth=2pt borderbottomcolor=black};
title '4) Using RTF control strings';
column section column1 column2 column3 column4 column5;
define section / order order=data noprint;
define column1 / "Column 1";
define column2 /  "Column 2";
define column3 /  "Column 3";
define column4 /  "Column 4";
define column5 /  "Column 5";
compute after section /
        style={protectspecialchars=off};
  line '\brdrt\brdrs ';
endcomp;
run;
ods _all_ close;
    
ods rtf file='c:\temp\diff_by.rtf' style=journal startpage=no;
  
** another approach using BY;
proc report data=lines NOWINDOWS
     STYLE(report)=[frame=box rules=cols]
     style(header)={borderbottomwidth=2pt borderbottomcolor=black};
title '5) Using BY groups';
by section;
column section column1 column2 column3 column4 column5;
define section / order order=data noprint;
define column1 / "Column 1";
define column2 /  "Column 2";
define column3 /  "Column 3";
define column4 /  "Column 4";
define column5 /  "Column 5";
run;
   
ods _all_ close;
    
ods rtf file='c:\temp\diff_page.rtf' style=journal startpage=no;

** another approach without BY and with PAGE;
proc report data=lines NOWINDOWS
     STYLE(report)=[frame=box rules=cols]
     style(header)={borderbottomwidth=2pt borderbottomcolor=black};
title '6) Using PAGE for section groups';
column section column1 column2 column3 column4 column5;
define section / order order=data noprint;
define column1 / "Column 1";
define column2 /  "Column 2";
define column3 /  "Column 3";
define column4 /  "Column 4";
define column5 /  "Column 5";
break after section / page;
run;
   
ods _all_ close;


horizontal_lines_rtf_simple_choices.png
KaySca81
Calcite | Level 5

@Cynthia: Thank you very much for all the examples!!!

I got another idea when I was trying your examples - you can use the compute statement to get the lines without having another row. So I just had to add the following code to my proc report statement:

compute after section;

if section ne . then call define (_row_, 'style', 'style=[bordertopwidth=2pt]');

endcomp;

So, I got pointed in another direction because of your examples, thanks a lot!

Sabrina

sas-innovate-2024.png

Don't miss out on SAS Innovate - Register now for the FREE Livestream!

Can't make it to Vegas? No problem! Watch our general sessions LIVE or on-demand starting April 17th. Hear from SAS execs, best-selling author Adam Grant, Hot Ones host Sean Evans, top tech journalist Kara Swisher, AI expert Cassie Kozyrkov, and the mind-blowing dance crew iLuminate! Plus, get access to over 20 breakout sessions.

 

Register now!

How to Concatenate Values

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.

Click image to register for webinarClick image to register for webinar

Classroom Training Available!

Select SAS Training centers are offering in-person courses. View upcoming courses for:

View all other training opportunities.

Discussion stats
  • 5 replies
  • 13488 views
  • 5 likes
  • 2 in conversation