Suppose that one page can contain up to 35 lines of data besides table title, table header and table footnote. And you set value of a page number variable to be 1 for these 35 rows of data and use Break after statement to create page break and expect that these data will be placed in one page. However, you will find that extra blank spaces are added at end of first page and part of data are placed in second page if you use ODS TAGSETS.RTF. SAS does not work as expected.

But if you move data from second page into first page manually, you will find that one page is enough to contain these data.

Anything wrong with our SAS code? After reading SAS support document again and again and trying option after another option, you will quickly find that there is no way to remove these annoying blank spaces via SAS supplied options. Frustrated?

It took me a lot of time to find out where these spaces came from. Half year had passed and one day it occurred to me that it is ODS TAGSETS.RTF itself that create these blanks spaces. For ODS RTF destination, SAS determines horizontal measurement while Microsoft Word determines vertical measurement. For table longer than a physical page, Microsoft Word will set inappropriate and implicit page break and thus title/footnote will not be displayed in each page.

To fix this issue, SAS launched ODS TAGSETS.RTF which is referred to as the measured TAGSET. It not only can control the horizontal measurement with Width option in Define statement, but also the vertical measurement. It will compute how much room there is on the page and how much room the data needs and then calculate page break based on these two kinds of data. If the data requires more space, SAS will create a new page for these data. This intention is good. However, the calculations are not accurate, and this is the source where these blank spaces come from.

To remove these blank spaces, we can read RTF into SAS dataset and then remove unexpected page break, footnote, title and table headers and then put updated SAS dataset into RTF again. RTF code highlighted in gray are those should be removed.

Here are the SAS code for you to remove these RTF code.

 
proc template;
  define style styles.rtftemp;
    parent = Styles.RTF;
    replace fonts / 
    'TitleFont' = ("Times New Roman",12pt,Bold) 
    'TitleFont2' = ("Times New Roman",10pt,Bold) 
    'StrongFont' = ("Times New Roman",10pt,Bold) 
    'EmphasisFont' = ("Times New Roman",10pt) 
    'headingEmphasisFont' = ("Times New Roman",10pt,Bold) 
    'headingFont' = ("Times New Roman",11pt,Bold) 
    'docFont' = ("Times New Roman",12pt,Bold) 
    'tableFont' = ("Times New Roman",11pt) 
    'footFont' = ("Times New Roman",10pt) 
    'FixedEmphasisFont' = ("Times New Roman",10pt) 
    'FixedStrongFont' = ("Times New Roman",10pt,Bold) 
    'FixedHeadingFont' = ("Times New Roman",10pt,Bold) 
    'BatchFixedFont' = ("Times New Roman",10pt) 
    'FixedFont' = ("Times New Roman",10pt);

    replace color_list / 
    'link' = blue 
    'bgH' = _undef_ 
    'fg' = black 
    'bg' = _undef_;

    replace Body from Body / 
    topmargin = 1 in 
    bottommargin = 1 in 
    leftmargin = 1 in 
    rightmargin = 1 in 
    protectspecialchars = off 
    outputwidth = 100%;

    style Table from Table / 
    frame = hsides 
    rules = groups 
    cellpadding = 0pt 
    cellspacing = 0pt 
    borderwidth = 0.5pt 
    outputwidth = 100% 
    Background=_undef_ 
    protectspecialchars = off;

    style PrePage from PrePage/ 
    outputwidth = 100% 
    asis = on 
    just = left 
    protectspecialchars = off;

    replace Header from Header / 
    asis = on 
    just = center 
    protectspecialchars = off;

    replace Data from Data / 
    font = Fonts('tableFont') 
    asis = on 
    just = center 
    protectspecialchars = off;

    style UserText from UserText/ 
    font = Fonts('footFont') 
    outputwidth = 100% 
    asis = on 
    just = left 
    protectspecialchars = off;

    replace SystemFooter from TitlesAndFooters / 
    font = Fonts('footFont') 
    asis=on 
    outputwidth = 100%;

    style GraphFonts "Fonts used in graph styles"/ 
    'GraphDataFont'=("Times New Roman",9pt) 
    'GraphUnicodeFont'=("Times New Roman",9pt) 
    'GraphValueFont'=("Times New Roman",9pt) 
    'GraphValueTextFont'=("Times New Roman",9pt) 
    'GraphLabelFont'=("Times New Roman",9pt) 
    'GraphFootnoteFont'=("Times New Roman",9pt) 
    'GraphTitleFont'=("Times New Roman",9pt) 
    'GraphAnnoFont'=("Times New Roman",9pt) 
    'NodeLinkLabelFont'=("Times New Roman",9pt) 
    'GraphLabel2Font'=("Times New Roman",9pt) 
    'GraphTitle1Font'=("Times New Roman",9pt) 
    'NodeTitleFont'=("Times New Roman",9pt) 
    'NodeLabelFont'=("Times New Roman",9pt) 
    'NodeInputLabelFont'=("Times New Roman",9pt) 
    'NodeDetailFont'=("Times New Roman",9pt);

    style parskip / fontsize = 0pt;

    style graphaxislines from graphaxislines / 
        linestyle=1 linethickness=2px;

    style graph from graph / 
          bordercolor=black borderwidth=2px;
  end;
run;

title1 j = c "\s1 Table 14.3.2.2 \line Summary of TEAE by MedDRA System Organ Class and Preferred Term \line Safety Analysis Set";
title2 j = l "\s2    ";

footnote1 j=l "Source: xxx";
footnote2 j=l "Data extraction: 22Jul2019, Data cut-off: 22Jul2019";
footnote3 j=l "Abbreviations: DLT = dose limiting toxicity; SAE = serious adverse event; TEAE = treatment adverse event. 
\line All percentages are based on N.";

goptions device=actximg;
options orientation=portrait nodate nonumber;
ods escapechar= "^";
ods tagsets.rtf file="E:/t-ae.rtf"  style=Styles.rtftemp nogtitle nogfootnote 
options(vspace="no" tables_off="prepage usertext" continue_tag="on") ;

ods listing close;

proc report data= x nowd missing split='~';
    column pgno ord seq col1 col2 col3 col4;
    define PGNO / order order = internal noprint "" ;
    define ORD / order order = internal noprint "" ;
    define SEQ / order order = internal noprint "" ;
    define COL1 / "Response Category~" style(header)=[just = left] style(column)=[just = left cellwidth = 15% ] ;
    define COL2 / "Arm 1~(N = XX)~n(%)" style(header)=[just = center] style(column)=[just = center cellwidth = 5%] ;
    define COL3 / "Arm 2~(N = XX)~n(%)" style(header)=[just = center] style(column)=[just = center cellwidth = 5%] ;
    define COL4 / "Arm 3~(N = XX)~n(%)" style(header)=[just = center] style(column)=[just = center cellwidth = 5%] ;
    break after pgno/page;
run;
  
ods listing;
ods tagsets.rtf close;


data m_pgno;
  retain continued_fl continued_hdfl continued_nofl;
  length rtfcode $8192;
  infile "E:/t-ae.rtf" lrecl = 8192 end = eof;
  input ;
  rtfcode = _infile_;
    if index(rtfcode, "\trowd\trkeep\trqc\trgaph0\pard\plain\intbl\sl-5{\cell}\clbrdrt\brdrs\brdrw10\brdrcf1" 
                   ) then continued_fl = "Y";
    if continued_fl = "Y" and rtfcode = "\trowd\trkeep\trhdr\trqc\trgaph0" then continued_hdfl = "Y";
    if index(rtfcode, "{\*\bkmkstart") and index(rtfcode,"{\*\bkmkend") then do;
       continued_fl = "";
       continued_hdfl = "";
       continued_nofl = "";
    end;
    if continued_fl = "Y" and continued_hdfl = "Y" and rtfcode = "\trowd\trkeep\trqc\trgaph0" then continued_nofl = "Y";

    if continued_fl = "Y" and continued_nofl = "" then delete;
run;

data _null_;
  file "E:/t-ae.rtf";
  set  m_pgno;

  put rtfcode;
run;