Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refining split #19

Merged
merged 7 commits into from
Nov 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 2 additions & 3 deletions DESCRIPTION
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,5 @@ Roxygen: list(markdown = TRUE)
RoxygenNote: 7.3.2
Collate:
'package.R'
'tt_export.R'
'tt_as_flextable.R'
'tt_to_paginate_office.R'
'export_as_docx.R'
'as_flextable.R'
6 changes: 0 additions & 6 deletions NAMESPACE
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
# Generated by roxygen2: do not edit by hand

export(export_as_docx)
export(export_as_pdf)
export(export_as_txt)
export(margins_landscape)
export(margins_potrait)
export(section_properties_default)
Expand All @@ -15,10 +13,6 @@ import(formatters)
import(methods)
import(officer)
import(rtables)
importFrom(formatters,export_as_pdf)
importFrom(formatters,export_as_txt)
importFrom(lifecycle,deprecated)
importFrom(magrittr,"%>%")
importFrom(rtables,import_from_tsv)
importFrom(stats,setNames)
importFrom(tools,file_ext)
56 changes: 25 additions & 31 deletions R/tt_as_flextable.R → R/as_flextable.R
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@
#' @param autofit_to_page (`flag`)\cr defaults to `TRUE`. If `TRUE`, the column widths are automatically adjusted to
#' fit the total page width. If `FALSE`, the `colwidths` are used as an indicative proportion of `total_page_width`.
#' See `flextable::set_table_properties(layout)` for more details.
#' @param ... (`any`)\cr additional parameters to be passed to the pagination function. See [paginate_table()]
#' @param ... (`any`)\cr additional parameters to be passed to the pagination function. See [rtables::paginate_table()]
#' for further details.
#'
#' @return A `flextable` object.
Expand All @@ -57,9 +57,9 @@
#' theme like shown in the examples. Please pay attention to the parameters' inputs as they are relevant
#' for this to work properly.
#' Indeed, it is possible to use some hidden values for building your own theme (hence the need of `...`).
#' In particular, `tt_to_flextable` sends in the following variable: `tbl_row_class = make_row_df(tt)$node_class`.
#' This is ignored if not used in the theme. See `theme_docx_default` for an example on own to retrieve
#' these values and how to use them.
#' In particular, `tt_to_flextable` sends in the following variable:
#' `tbl_row_class = rtables::make_row_df(tt)$node_class`. This is ignored if not used in the theme.
#' See `theme_docx_default` for an example on own to retrieve these values and how to use them.
#'
#' @seealso [export_as_docx()]
#'
Expand All @@ -82,9 +82,6 @@
#'
#' tbl <- build_table(lyt, ex_adsl)
#'
#' @examples
#' # example code
#'
#' # rtables style
#' tt_to_flextable(tbl, theme = NULL)
#'
Expand Down Expand Up @@ -116,7 +113,6 @@ tt_to_flextable <- function(tt,
total_page_height = 10, # portrait 11 landscape 8.5
total_page_width = 10, # portrait 8.5 landscape 11
autofit_to_page = TRUE) {
check_required_packages("flextable")
if (!inherits(tt, "VTableTree")) {
stop("Input table is not an rtables' object.")
}
Expand Down Expand Up @@ -169,7 +165,7 @@ tt_to_flextable <- function(tt,
" each table will be too long to fit each page."
)
}
tabs <- paginate_table(tt,
tabs <- rtables::paginate_table(tt,
fontspec = fontspec,
lpp = lpp,
cpp = cpp, tf_wrap = tf_wrap, max_width = max_width, # This can only be trial an error
Expand All @@ -193,16 +189,16 @@ tt_to_flextable <- function(tt,
}

# Extract relevant information
matform <- matrix_form(tt, fontspec = fontspec, indent_rownames = FALSE)
body <- mf_strings(matform) # Contains header
spans <- mf_spans(matform) # Contains header
mpf_aligns <- mf_aligns(matform) # Contains header
hnum <- mf_nlheader(matform) # Number of lines for the header
rdf <- make_row_df(tt) # Row-wise info
matform <- rtables::matrix_form(tt, fontspec = fontspec, indent_rownames = FALSE)
body <- formatters::mf_strings(matform) # Contains header
spans <- formatters::mf_spans(matform) # Contains header
mpf_aligns <- formatters::mf_aligns(matform) # Contains header
hnum <- formatters::mf_nlheader(matform) # Number of lines for the header
rdf <- rtables::make_row_df(tt) # Row-wise info

# decimal alignment pre-proc
if (any(grepl("dec", mpf_aligns))) {
body <- decimal_align(body, mpf_aligns)
body <- formatters::decimal_align(body, mpf_aligns)
# Coercion for flextable
mpf_aligns[mpf_aligns == "decimal"] <- "center"
mpf_aligns[mpf_aligns == "dec_left"] <- "left"
Expand Down Expand Up @@ -294,7 +290,7 @@ tt_to_flextable <- function(tt,
# If there are more rows -> add them
if (hnum > 1) {
for (i in seq(hnum - 1, 1)) {
sel <- spans_to_viscell(spans[i, ])
sel <- formatters::spans_to_viscell(spans[i, ])
flx <- flextable::add_header_row(
flx,
top = TRUE,
Expand Down Expand Up @@ -364,13 +360,13 @@ tt_to_flextable <- function(tt,
}

# Footer lines
if (length(all_footers(tt)) > 0 && isFALSE(footers_as_text)) {
flx <- flextable::add_footer_lines(flx, values = all_footers(tt)) %>%
if (length(formatters::all_footers(tt)) > 0 && isFALSE(footers_as_text)) {
flx <- flextable::add_footer_lines(flx, values = formatters::all_footers(tt)) %>%
.add_hborder(part = "body", ii = nrow(tt), border = border)
}

# Apply the theme
flx <- .apply_themes(flx, theme = theme, tbl_row_class = make_row_df(tt)$node_class)
flx <- .apply_themes(flx, theme = theme, tbl_row_class = rtables::make_row_df(tt)$node_class)

# lets do some digging into the choice of fonts etc
if (is.null(fontspec)) {
Expand All @@ -379,14 +375,14 @@ tt_to_flextable <- function(tt,
# Calculate the needed colwidths
if (is.null(colwidths)) {
# what about margins?
colwidths <- propose_column_widths(matform, fontspec = fontspec, indent_size = indent_size)
colwidths <- formatters::propose_column_widths(matform, fontspec = fontspec, indent_size = indent_size)
}

# Title lines (after theme for problems with lines)
if (titles_as_header && length(all_titles(tt)) > 0 && any(nzchar(all_titles(tt)))) {
flx <- .add_titles_as_header(flx, all_titles = all_titles(tt), bold = bold_titles) %>%
if (titles_as_header && length(formatters::all_titles(tt)) > 0 && any(nzchar(formatters::all_titles(tt)))) {
flx <- .add_titles_as_header(flx, all_titles = formatters::all_titles(tt), bold = bold_titles) %>%
flextable::border(
part = "header", i = length(all_titles(tt)),
part = "header", i = length(formatters::all_titles(tt)),
border.bottom = border
)
}
Expand Down Expand Up @@ -416,8 +412,8 @@ tt_to_flextable <- function(tt,
# only used in pagination
.tab_to_colpath_set <- function(tt) {
vapply(
collect_leaves(coltree(tt)),
function(y) paste(pos_to_path(rtables:::tree_pos(y)), collapse = " "),
rtables::collect_leaves(rtables::coltree(tt)),
function(y) paste(rtables:::pos_to_path(rtables:::tree_pos(y)), collapse = " "),
""
)
}
Expand Down Expand Up @@ -477,7 +473,7 @@ tt_to_flextable <- function(tt,
font_fam <- test_flx$header$styles$text$font.family$data[1, 1]
font_fam <- "Courier" # Fix if we need it -> coming from gpar and fontfamily Arial not being recognized

font_spec(font_family = font_fam, font_size = font_sz, lineheight = 1)
formatters::font_spec(font_family = font_fam, font_size = font_sz, lineheight = 1)
}

.apply_alignments <- function(flx, aligns_df, part) {
Expand Down Expand Up @@ -569,7 +565,6 @@ theme_docx_default <- function(font = "Arial",
bold_manual = NULL,
border = flextable::fp_border_default(width = 0.5)) {
function(flx, ...) {
check_required_packages("flextable")
if (!inherits(flx, "flextable")) {
stop(sprintf(
"Function `%s` supports only flextable objects.",
Expand Down Expand Up @@ -637,13 +632,13 @@ theme_docx_default <- function(font = "Arial",
# Content rows are effectively our labels in row names
if (any(bold == "content_rows")) {
if (is.null(tbl_row_class)) {
stop('bold = "content_rows" needs tbl_row_class = make_row_df(tt).')
stop('bold = "content_rows" needs tbl_row_class = rtables::make_row_df(tt).')
}
flx <- flextable::bold(flx, j = 1, i = which(tbl_row_class == "ContentRow"), part = "body")
}
if (any(bold == "label_rows")) {
if (is.null(tbl_row_class)) {
stop('bold = "content_rows" needs tbl_row_class = make_row_df(tt).')
stop('bold = "content_rows" needs tbl_row_class = rtables::make_row_df(tt).')
}
flx <- flextable::bold(flx, j = 1, i = which(tbl_row_class == "LabelRow"), part = "body")
}
Expand All @@ -670,7 +665,6 @@ theme_html_default <- function(font = "Courier",
remove_internal_borders = "label_rows",
border = flextable::fp_border_default(width = 1, color = "black")) {
function(flx, ...) {
check_required_packages("flextable")
if (!inherits(flx, "flextable")) {
stop(sprintf(
"Function `%s` supports only flextable objects.",
Expand Down
116 changes: 51 additions & 65 deletions R/tt_export.R → R/export_as_docx.R
Original file line number Diff line number Diff line change
@@ -1,59 +1,3 @@
#' @importFrom tools file_ext
NULL

check_required_packages <- function(pkgs) {
for (pkgi in pkgs) {
if (!requireNamespace(pkgi, quietly = TRUE)) {
stop(
"This function requires the ", pkgi, " package. ",
"Please install it if you wish to use it"
)
}
}
}


# txt (formatters) --------------------------------------------------------------------
#' @importFrom formatters export_as_txt
#'
#' @examples
#' lyt <- basic_table() %>%
#' split_cols_by("ARM") %>%
#' analyze(c("AGE", "BMRKR2", "COUNTRY"))
#'
#' tbl <- build_table(lyt, ex_adsl)
#'
#' cat(export_as_txt(tbl, file = NULL, paginate = TRUE, lpp = 8))
#'
#' \dontrun{
#' tf <- tempfile(fileext = ".txt")
#' export_as_txt(tbl, file = tf)
#' system2("cat", tf)
#' }
#'
#' @export
formatters::export_as_txt

# pdf (formatters) ----------------------------------------------------------
#' @importFrom formatters export_as_pdf
#'
#' @examples
#' lyt <- basic_table() %>%
#' split_cols_by("ARM") %>%
#' analyze(c("AGE", "BMRKR2", "COUNTRY"))
#'
#' tbl <- build_table(lyt, ex_adsl)
#'
#' \dontrun{
#' tf <- tempfile(fileext = ".pdf")
#' export_as_pdf(tbl, file = tf, pg_height = 4)
#' tf <- tempfile(fileext = ".pdf")
#' export_as_pdf(tbl, file = tf, lpp = 8)
#' }
#'
#' @export
formatters::export_as_pdf

# docx (flextable) -----------------------------------------------------------
#' Export as word document
#'
Expand All @@ -74,7 +18,7 @@ formatters::export_as_pdf
#' @param ... (`any`)\cr additional arguments passed to [tt_to_flextable()].
#'
#' @note `export_as_docx()` has few customization options available. If you require specific formats and details,
#' we suggest that you use [tt_to_flextable()] prior to `export_as_docx`. Only the `title_as_header` and
#' we suggest that you use [tt_to_flextable()] prior to `export_as_docx`. Only the `titles_as_header` and
#' `footer_as_text` parameters must be re-specified if the table is changed first using [tt_to_flextable()].
Melkiades marked this conversation as resolved.
Show resolved Hide resolved
#'
#' @seealso [tt_to_flextable()]
Expand Down Expand Up @@ -103,7 +47,6 @@ export_as_docx <- function(tt,
section_properties = section_properties_default(),
...) {
# Checks
check_required_packages(c("flextable", "officer"))
if (inherits(tt, "VTableTree")) {
flex_tbl <- tt_to_flextable(tt,
titles_as_header = titles_as_header,
Expand All @@ -125,8 +68,36 @@ export_as_docx <- function(tt,
fpt <- officer::fp_text(font.family = font_fam, font.size = font_sz_body)
fpt_footer <- officer::fp_text(font.family = font_fam, font.size = font_sz_footer)
}
} else {
} else if (inherits(tt, "flextable")) {
flex_tbl <- tt
} else if (inherits(tt, "list")) {
export_as_docx(tt[[1]], # First paginated table that uses template_file
file = file,
doc_metadata = doc_metadata,
titles_as_header = titles_as_header,
footers_as_text = footers_as_text,
template_file = template_file,
section_properties = section_properties,
...
)
if (length(tt) > 1) {
out <- mapply(
export_as_docx,
tt = tt[-1], # Remaining paginated tables
MoreArgs = list(
file = file,
doc_metadata = doc_metadata,
titles_as_header = titles_as_header,
footers_as_text = footers_as_text,
template_file = file, # Uses the just-created file as template
section_properties = section_properties,
...
)
)
}
return()
} else {
stop("The table must be a VTableTree, a flextable, or a list of VTableTree or flextable objects.")
}
if (!is.null(template_file) && !file.exists(template_file)) {
template_file <- NULL
Expand All @@ -139,13 +110,26 @@ export_as_docx <- function(tt,
doc <- officer::read_docx()
}

if (!is.null(section_properties)) {
doc <- officer::body_set_default_section(doc, section_properties)
# page width and orientation settings
doc <- officer::body_set_default_section(doc, section_properties)
if (flex_tbl$properties$layout != "autofit") { # fixed layout
page_width <- section_properties$page_size$width
dflx <- dim(flex_tbl)
if (abs(sum(unname(dflx$widths)) - page_width) > 1e-2) {
warning(
"The total table width does not match the page width. The column widths",
" will be resized to fit the page. Please consider modifying the parameter",
" total_page_width in tt_to_flextable()."
)

final_cwidths <- page_width * unname(dflx$widths) / sum(unname(dflx$widths))
flex_tbl <- flextable::width(flex_tbl, width = final_cwidths)
}
}

# Extract title
if (isFALSE(titles_as_header) && inherits(tt, "VTableTree")) {
ts_tbl <- all_titles(tt)
ts_tbl <- formatters::all_titles(tt)
if (length(ts_tbl) > 0) {
doc <- add_text_par(doc, ts_tbl, fpt)
}
Expand All @@ -158,13 +142,13 @@ export_as_docx <- function(tt,
if (isTRUE(footers_as_text) && inherits(tt, "VTableTree")) {
# Adding referential footer line separator if present
# (this is usually done differently, i.e. inside footnotes)
matform <- matrix_form(tt, indent_rownames = TRUE)
matform <- rtables::matrix_form(tt, indent_rownames = TRUE)
if (length(matform$ref_footnotes) > 0) {
doc <- add_text_par(doc, matform$ref_footnotes, fpt_footer)
}
# Footer lines
if (length(all_footers(tt)) > 0) {
doc <- add_text_par(doc, all_footers(tt), fpt_footer)
if (length(formatters::all_footers(tt)) > 0) {
doc <- add_text_par(doc, formatters::all_footers(tt), fpt_footer)
}
}

Expand All @@ -175,6 +159,8 @@ export_as_docx <- function(tt,

# Save the Word document to a file
print(doc, target = file)

invisible(TRUE)
}

# Shorthand to add text paragraph
Expand Down
1 change: 0 additions & 1 deletion R/package.R
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
#' @import methods
#' @import formatters
#' @import rtables
#' @importFrom rtables import_from_tsv
#' @import officer
#' @import flextable
NULL
17 changes: 0 additions & 17 deletions R/tt_to_paginate_office.R

This file was deleted.

Loading
Loading