Merck / r2rtf

Easily Create Production-Ready Rich Text Format (RTF) Table and Figure
https://merck.github.io/r2rtf
GNU General Public License v3.0
76 stars 19 forks source link

Any way to show footnotes on every page? #169

Closed Chuck1111 closed 1 year ago

Chuck1111 commented 1 year ago

Question Now I can add footnotes to the last page of the rtf output. Is there a way to add the same footnotes at the end of each page in the rtf output?

Thank you in advance!

fb-elong commented 1 year ago

check page_footnote argument in rtf_encode function. https://merck.github.io/r2rtf/reference/rtf_encode.html

Chuck1111 commented 1 year ago

Thank you @fb-elong ! Another question related to the footnotes, I was able to add the footnotes to all the pages following your advise. But when the table is short on the last page, the footnote will attach to the table wherever it ends. For example, if the table on the page only has 2 rows, then the footnote starts at the third row. Is there any way to make it attach to the end of the page as well on the last page of table?

fb-elong commented 1 year ago

Please provide a reproducible example, so we can further investigate.

reference: https://reprex.tidyverse.org/

Chuck1111 commented 1 year ago

Hi elong, Thank you for getting back! I have the code from reprex attached. So it might be easier for me to list all the issues I can see now here:

  1. In the rtf output, there is a blank page after 1 or 2 pages.
  2. ifelse does not work in rtf_page function
  3. The footnote on the last page is in the middle of the page, is there any way to make it displays at the bottom?
  4. Maybe it's already there but I did not find it, can we do 'split' justification in the title and page header sections? For example, now I have to manually add spaces between '[Confidential]' and 'CSR' to make them display on left and right upper corners. Thank you again!
    
    library(r2rtf)
    #> Warning: package 'r2rtf' was built under R version 4.1.3
    library(glue)
    #> Warning: package 'glue' was built under R version 4.1.3
    library(dplyr)
    #> Warning: package 'dplyr' was built under R version 4.1.3
    #> 
    #> Attaching package: 'dplyr'
    #> The following objects are masked from 'package:stats':
    #> 
    #>     filter, lag
    #> The following objects are masked from 'package:base':
    #> 
    #>     intersect, setdiff, setequal, union
    n_trt <- 100
    n_placebo <- 50
    # Create empty dataframe
    df <- data.frame(matrix(ncol = 6, nrow = 200))

Assign column names

colnames(df) <- c("Column1", "Column2", "Column3", "Column4", "Column5", "Column6")

Generate random character data

set.seed(123) # For reproducibility for (i in 1:6) { df[, i] <- replicate(200, paste(sample(letters, 5, replace = TRUE), collapse = "")) }

df %>%

rtf_page(orientation = "landscape") %>%

rtf_page(orientation = "landscape",

width = ifelse(orientation == "portrait", 8.5, 11),

       # height = ifelse(orientation == "portrait", 11, 8.5),
       # nrow = ifelse(orientation == "portrait", 40, 24)
       width = 11,
       height = 8.5,
       nrow = 35

) %>% rtf_page_header(text = "[CONFIDENTIAL] CSR \line Protocol XL184-311 Page \pagenumber of \pagefield", text_justification = "j", text_font_size = 8, text_convert = TRUE ) %>% rtf_footnote( footnote = c("Note: At each level of subject summarization, a subject is counted once for the most severe event if the subject reported one or more events. * Indicates p-value < 0.05. MedDRA 23.0 used for coding", "[1] All odds ratios, relative risks and risk differences are for comparing the Cabozantinib only arm to the Placebo arm", "All point estimates and confidence intervals are from Proc Freq, odds ratio p-values from Proc Logistic, Relative risk p-values from Proc Genmod and Risk difference CMH p-value from proc Freq. P-values for the odds ratio and relative risk are not generated unless the event rate is at least 5% in both the treatment arms.", "Source Data: ADSL, ADAE", "Data Cut Date: 19AUG2020 Data Extraction Date: 13NOV2020", "Source: Data transfer: 20210316" ), as_table = FALSE, #If TRUE, the footnotes will be inside the table

text_space_before = 5,

text_font_size = 7,
text_convert = FALSE #Tell R don't interpret special characters

) %>% rtf_title(title = c( "Table 14.3.1.5.7.1", "Subject Incidence of Treatment-Emergent Adverse Events by Preferred Term with Odds Ratio, Relative Risk and Risk Difference", "(sorted by Descending Risk Difference)", "Population: Safety" ), text_font_size = 9 ) %>%

rtf_subline(text= subline) %>%

rtf_colheader(colheader = " |Treatment 1| |Oddsd Ratio [1]|Relative Risk [1]|Risk Difference [1]", col_rel_width = c(5,3,3,3,3,3), border_left = "", border_right = "", border_bottom = "", text_font_size=8 ) %>% rtf_colheader(colheader = " |Only|Placebo|(95% CI)|(95% CI)|(95% CI)", col_rel_width = c(5,3,3,3,3,3), border_left = "", border_right = "", border_top = "", text_font_size=8 ) %>% rtf_colheader(colheader = glue('Preferred Term|(N={n_trt})|(N={n_placebo})|p-value|p-value|p-value'), col_rel_width = c(5,3,3,3,3,3), border_top = "", border_left = "", border_right = "", text_justification = c('l',rep('c',5)), text_font_size=8) %>% rtf_body(col_rel_width = c(5,3,3,3,3,3), text_justification = c('l',rep('c',5)), border_left = "", border_right = "", text_font_size=8) %>% rtf_encode(page_footnote = 'all') %>% write_rtf(paste0("test1",".rtf"))



<sup>Created on 2023-05-30 with [reprex v2.0.2](https://reprex.tidyverse.org)</sup>
elong0527 commented 1 year ago

In the rtf output, there is a blank page after 1 or 2 pages.

Set nrow = 34 instead of 35 in rtf_page. RTF automatically go to next page (there is a blank line) when you do not have enough space. Alternatively, reduce page margin to provide you more space.

ifelse does not work in rtf_page function

you have not define orientation variable if you mean those code in the comment.

orientation <-  "landscape"
  rtf_page(orientation =orientation,
           width = ifelse(orientation == "portrait", 8.5, 11),
           # height = ifelse(orientation == "portrait", 11, 8.5),
           # nrow = ifelse(orientation == "portrait", 40, 24)
           width = 11,
           height = 8.5,
           nrow = 34
  )

The footnote on the last page is in the middle of the page, is there any way to make it displays at the bottom?

Use rtf_page_footer https://merck.github.io/r2rtf/reference/rtf_page_footer.html

Maybe it's already there but I did not find it, can we do 'split' justification in the title and page header sections? For example, now I have to manually add spaces between '[Confidential]' and 'CSR' to make them display on left and right upper corners. Thank you again!

Unfortunately, there is no option for this in r2rtf. The page title and page footer is a paragraph. Using proper number of spaces is what I would do as well. The code below may be easier for you to control the space.

glue::glue("[CONFIDENTIAL] {paste(rep(' ', 20), collapse = '')}CSR \\line Protocol XL184-311{paste(rep(' ', 20), collapse = '')}Page \\pagenumber of \\pagefield")
Chuck1111 commented 1 year ago

Hi elong,

Thanks for the detailed explanation! The only issue now I am still experiencing is the nrow option in rtf_page(). If you look carefully in the output generated by the codes I provided, the first page is always has a shorter size than the rest of pages. And in some of my testing cases with real data, the first page is much shorter than the other pages. I did not find the causes, why in some cases it's one row shorter, and in others, it's multiple rows shorter. But is there any way to fix this different sizes on different pages issue?

Thank you!

fb-elong commented 1 year ago

There are several reason for this behavior while r2rtf derive which row going to which page. From design perspective, we calculate number of line per page in a conservative way.

e.g. if you have a column with text close to the width of the cells, it can be counted as two lines, but you may only see one line in the output.

Chuck1111 commented 1 year ago

Hi elong,

Then what would you suggest if it comes from the package design? I really like the r2rtf package, but I need my outputs to have the same sizes on all the pages.

In the example you gave below, I think this maybe what happened to my outputs since some of the AE terms are long. But why only the first page size is different from the other pages?

e.g. if you have a column with text close to the width of the cells, it can be counted as two lines, but you may only see one line in the output.

Thanks!

fb-elong commented 1 year ago

Could you provide a reproducible example? I didn't see this issue in the code you provided after changing 35 -> 34 for the nrow argument.

library(r2rtf)
#> Warning: package 'r2rtf' was built under R version 4.1.3
library(glue)
#> Warning: package 'glue' was built under R version 4.1.3
library(dplyr)
#> Warning: package 'dplyr' was built under R version 4.1.3
#> 
#> Attaching package: 'dplyr'
#> The following objects are masked from 'package:stats':
#> 
#>     filter, lag
#> The following objects are masked from 'package:base':
#> 
#>     intersect, setdiff, setequal, union
n_trt <- 100
n_placebo <- 50
# Create empty dataframe
df <- data.frame(matrix(ncol = 6, nrow = 200))

# Assign column names
colnames(df) <- c("Column1", "Column2", "Column3", "Column4", "Column5", "Column6")

# Generate random character data
set.seed(123)  # For reproducibility
for (i in 1:6) {
  df[, i] <- replicate(200, paste(sample(letters, 5, replace = TRUE), collapse = ""))
}

df %>%
  # rtf_page(orientation = "landscape") %>%
  rtf_page(orientation = "landscape",
           # width = ifelse(orientation == "portrait", 8.5, 11),
           # height = ifelse(orientation == "portrait", 11, 8.5),
           # nrow = ifelse(orientation == "portrait", 40, 24)
           width = 11,
           height = 8.5,
           nrow = 35
  ) %>%
  rtf_page_header(text = "[CONFIDENTIAL]                                                                                                                CSR \\line Protocol XL184-311                                                                                                                   Page \\pagenumber of \\pagefield",
                  text_justification = "j",
                  text_font_size = 8,
                  text_convert = TRUE
  ) %>%
  rtf_footnote(
    footnote = c("Note: At each level of subject summarization, a subject is counted once for the most severe event if the subject reported one or more events. * Indicates p-value < 0.05. MedDRA 23.0 used for coding",
                 "[1] All odds ratios, relative risks and risk differences are for comparing the Cabozantinib only arm to the Placebo arm",
                 "All point estimates and confidence intervals are from Proc Freq, odds ratio p-values from Proc Logistic, Relative risk p-values from Proc Genmod and Risk difference CMH p-value from proc Freq. P-values for the odds ratio and relative risk are not generated unless the event rate is at least 5% in both the treatment arms.",
                 "Source Data: ADSL, ADAE",
                 "Data Cut Date: 19AUG2020 Data Extraction Date: 13NOV2020",
                 "Source: Data transfer: 20210316"
    ),
    as_table = FALSE, #If TRUE, the footnotes will be inside the table
    # text_space_before = 5,
    text_font_size = 7,
    text_convert = FALSE #Tell R don't interpret special characters
  ) %>%
  rtf_title(title = c(
    "Table 14.3.1.5.7.1",
    "Subject Incidence of Treatment-Emergent Adverse Events by Preferred Term with Odds Ratio, Relative Risk and Risk Difference",
    "(sorted by Descending Risk Difference)",
    "Population: Safety"
  ),
  text_font_size = 9
  ) %>%
  # rtf_subline(text= subline) %>%
  rtf_colheader(colheader = " |Treatment 1| |Oddsd Ratio [1]|Relative Risk [1]|Risk Difference [1]",
                col_rel_width = c(5,3,3,3,3,3),
                border_left = "",
                border_right = "",
                border_bottom = "",
                text_font_size=8 ) %>%
  rtf_colheader(colheader = " |Only|Placebo|(95% CI)|(95% CI)|(95% CI)",
                col_rel_width = c(5,3,3,3,3,3),
                border_left = "",
                border_right = "",
                border_top = "",
                text_font_size=8 ) %>%
  rtf_colheader(colheader = glue('Preferred Term|(N={n_trt})|(N={n_placebo})|p-value|p-value|p-value'),
                col_rel_width = c(5,3,3,3,3,3),
                border_top = "",
                border_left = "",
                border_right = "",
                text_justification = c('l',rep('c',5)),
                text_font_size=8) %>%
  rtf_body(col_rel_width = c(5,3,3,3,3,3),
           text_justification = c('l',rep('c',5)),
           border_left = "",
           border_right = "",
           text_font_size=8) %>%
  rtf_encode(page_footnote = 'all') %>%
  write_rtf(paste0("test1",".rtf"))

image

fb-elong commented 1 year ago

Closing the issue as the original question of this issue has been fixed.

Please create a new issue for the particular question. Thanks!