From cdd740cd4f55ffaff349d8944d1202920fd4e49d Mon Sep 17 00:00:00 2001 From: Davide Garolini Date: Tue, 16 Jun 2026 14:35:08 +0000 Subject: [PATCH 1/3] Use autofit layout for add_forest() flextable A wide forest table kept a fixed layout and spilled off the page when saved to docx. Setting the flextable layout to autofit lets Word reflow the table to the page width while the plot column keeps its size. --- NEWS.md | 2 ++ R/add_forest.R | 5 ++++- tests/testthat/test-add_forest.R | 6 +++++- 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/NEWS.md b/NEWS.md index 80031441d..c4c098b2d 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,5 +1,7 @@ # crane 0.3.3 +* `add_forest()` now returns a flextable with an autofit layout so wide forest tables reflow to the page width instead of spilling off the page in docx output. (#270) + * Fixed minor typo in the DESCRIPTION file. # crane 0.3.2 diff --git a/R/add_forest.R b/R/add_forest.R index f5242412a..aa75ddcd2 100644 --- a/R/add_forest.R +++ b/R/add_forest.R @@ -235,7 +235,10 @@ add_forest <- function(x, flextable::padding(padding.top = 0, part = "body") |> flextable::padding(padding.bottom = 7, part = "body") |> flextable::padding(j = "ggplot", padding.bottom = 0, part = "body") |> - flextable::valign(valign = "bottom", part = "body") + flextable::valign(valign = "bottom", part = "body") |> + # without autofit the wide forest table keeps a fixed layout and spills + # off the page when saved to docx + flextable::set_table_properties(layout = "autofit") } out diff --git a/tests/testthat/test-add_forest.R b/tests/testthat/test-add_forest.R index 7f7c7ad40..bb3a4dacf 100644 --- a/tests/testthat/test-add_forest.R +++ b/tests/testthat/test-add_forest.R @@ -28,7 +28,7 @@ test_that("add_forest(table_engine = 'flextable') works", { ) expect_error( - tbl <- trial |> + forest_ft <- trial |> tbl_roche_subgroups( subgroups = c("grade", "stage"), rsp = "response", @@ -45,6 +45,10 @@ test_that("add_forest(table_engine = 'flextable') works", { ), NA ) + + # autofit layout lets Word reflow the wide table instead of spilling off the + # page in docx output (#270) + expect_identical(forest_ft$properties$layout, "autofit") }) test_that("add_forest handles extreme limits and character NA p-values safely", { From c4d480072fca6ee97e8a48e2cbc4d5666299e702 Mon Sep 17 00:00:00 2001 From: Davide Garolini Date: Thu, 18 Jun 2026 18:38:44 +0000 Subject: [PATCH 2/3] fix: make add_forest() flextable actually fit the page in docx `layout = "autofit"` alone emits tblW = 0% (Word "AutoFit to Contents"), which sizes columns to their natural width; the forest table (fixed 2.5in plot column plus non-wrapping stat columns, ~11.8in total) still overflows the page. Pair it with width = 1 to emit tblW = 100% ("AutoFit to Window") so Word scales the table to the page width while the plot images keep their 2.5in x 0.4in size. Assert the 100% preferred width in tests, and add autofit/docx/reflow to the spelling WORDLIST. --- NEWS.md | 2 +- R/add_forest.R | 9 +++++--- inst/WORDLIST | 39 +++++++++++++++++--------------- tests/testthat/test-add_forest.R | 7 ++++-- 4 files changed, 33 insertions(+), 24 deletions(-) diff --git a/NEWS.md b/NEWS.md index c4c098b2d..821714505 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,6 +1,6 @@ # crane 0.3.3 -* `add_forest()` now returns a flextable with an autofit layout so wide forest tables reflow to the page width instead of spilling off the page in docx output. (#270) +* `add_forest()` now returns a flextable that fits the page width (autofit layout at 100% preferred width) so wide forest tables no longer spill off the page in docx output. (#270) * Fixed minor typo in the DESCRIPTION file. diff --git a/R/add_forest.R b/R/add_forest.R index aa75ddcd2..29249eb2f 100644 --- a/R/add_forest.R +++ b/R/add_forest.R @@ -236,9 +236,12 @@ add_forest <- function(x, flextable::padding(padding.bottom = 7, part = "body") |> flextable::padding(j = "ggplot", padding.bottom = 0, part = "body") |> flextable::valign(valign = "bottom", part = "body") |> - # without autofit the wide forest table keeps a fixed layout and spills - # off the page when saved to docx - flextable::set_table_properties(layout = "autofit") + # The forest table is wider than the page. `layout = "autofit"` alone + # emits `tblW = 0%` (Word "AutoFit to Contents"), which sizes columns to + # their natural width and still overflows. Pairing it with `width = 1` + # emits `tblW = 100%` ("AutoFit to Window") so Word scales the table to + # the page width while the plot column keeps its 2.5in x 0.4in images. + flextable::set_table_properties(layout = "autofit", width = 1) } out diff --git a/inst/WORDLIST b/inst/WORDLIST index 0a17e3c7f..bf74d5b79 100644 --- a/inst/WORDLIST +++ b/inst/WORDLIST @@ -1,54 +1,57 @@ +ADaM ADEX ADSL -ADaM AE AEs +analyte ARD ARDs -GDSR -HLT -Hoffmann -Kaplan -MMRM -Ns -ORCID -PY -Pharmacokinetic -Pharmacokinetics -RMP -RMPT -RStudio -Rua -SOCs -Tidyverse -analyte +autofit breslow cardx custiomization customizations de +docx efron fleming flextable funder +GDSR gehan ggplot gtsummary harrington +HLT +Hoffmann +Kaplan lineplot lineplots +MMRM +Ns +ORCID peto pharma +Pharmacokinetic +Pharmacokinetics pre prentice +PY quosure quosures +reflow responder rlang's +RMP +RMPT +RStudio +Rua +SOCs survfit tarone tbl tidyselect +Tidyverse unpooled unstratified wilcoxon diff --git a/tests/testthat/test-add_forest.R b/tests/testthat/test-add_forest.R index bb3a4dacf..a1ba4d436 100644 --- a/tests/testthat/test-add_forest.R +++ b/tests/testthat/test-add_forest.R @@ -46,9 +46,12 @@ test_that("add_forest(table_engine = 'flextable') works", { NA ) - # autofit layout lets Word reflow the wide table instead of spilling off the - # page in docx output (#270) + # autofit layout + 100% preferred width lets Word reflow the wide table to + # the page ("AutoFit to Window") instead of spilling off the page in docx + # output. `layout = "autofit"` alone keeps a 0% preferred width ("AutoFit to + # Contents") and still overflows (#270). expect_identical(forest_ft$properties$layout, "autofit") + expect_identical(forest_ft$properties$width, 1) }) test_that("add_forest handles extreme limits and character NA p-values safely", { From 43fa83b826ce1eb81ae04cf1f1e2c2b43ec731de Mon Sep 17 00:00:00 2001 From: Davide Garolini Date: Fri, 19 Jun 2026 08:12:52 +0000 Subject: [PATCH 3/3] fix: fit add_forest() plot in flextable cell without overflow The forest-plot column has a fixed width and holds an image rendered to exactly that width. Under the theme's autofit layout Word sizes the column to its content's natural width, and the default 5pt horizontal cell padding pushes the image past the column, expanding the table until it overflows the page in docx. Zero the plot column's horizontal padding so the image fits its cell content box exactly; the plot proportions are unchanged. This supersedes the earlier autofit/100%-width attempts, which did not fix the overflow. --- NEWS.md | 2 +- R/add_forest.R | 23 +++++++++++-------- inst/WORDLIST | 38 +++++++++++++++----------------- tests/testthat/test-add_forest.R | 13 ++++++----- 4 files changed, 40 insertions(+), 36 deletions(-) diff --git a/NEWS.md b/NEWS.md index 821714505..c7744d7d7 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,6 +1,6 @@ # crane 0.3.3 -* `add_forest()` now returns a flextable that fits the page width (autofit layout at 100% preferred width) so wide forest tables no longer spill off the page in docx output. (#270) +* `add_forest()` now removes the horizontal padding of the forest-plot column in flextable output so the fixed-width plot fits its cell exactly and wide forest tables no longer spill off the page in docx. (#270) * Fixed minor typo in the DESCRIPTION file. diff --git a/R/add_forest.R b/R/add_forest.R index 29249eb2f..cc898735a 100644 --- a/R/add_forest.R +++ b/R/add_forest.R @@ -217,13 +217,21 @@ add_forest <- function(x, ") |> gt::tab_style(style = gt::cell_text(whitespace = "nowrap"), locations = gt::cells_body()) } else if (table_engine == "flextable") { + # The plot column has a fixed width. Render the image to exactly that width + # and remove the cell's horizontal padding so the raster fills its content + # box instead of being forced wider than the cell (which, under Word's fixed + # table layout, pushes the column out and makes the table overflow the page). + # The plot's proportions are unchanged; only the cell geometry is matched. + ggplot_col_width <- 2.5 out <- out |> gtsummary::as_flex_table() |> flextable::mk_par( j = "ggplot", value = flextable::as_paragraph( suppressMessages( # avoid `height` was translated to `width`. message - flextable::gg_chunk(value = lst_ggplots_final, height = 0.4, width = 2.5) + flextable::gg_chunk( + value = lst_ggplots_final, height = 0.4, width = ggplot_col_width + ) ) ) ) |> @@ -231,17 +239,14 @@ add_forest <- function(x, flextable::line_spacing(j = "ggplot", space = 0, part = "body") |> flextable::valign(valign = "center", part = "body") |> flextable::align(j = "ggplot", align = "center", part = "header") |> - flextable::width(j = "ggplot", width = 2.5) |> flextable::padding(padding.top = 0, part = "body") |> flextable::padding(padding.bottom = 7, part = "body") |> flextable::padding(j = "ggplot", padding.bottom = 0, part = "body") |> - flextable::valign(valign = "bottom", part = "body") |> - # The forest table is wider than the page. `layout = "autofit"` alone - # emits `tblW = 0%` (Word "AutoFit to Contents"), which sizes columns to - # their natural width and still overflows. Pairing it with `width = 1` - # emits `tblW = 100%` ("AutoFit to Window") so Word scales the table to - # the page width while the plot column keeps its 2.5in x 0.4in images. - flextable::set_table_properties(layout = "autofit", width = 1) + # zero horizontal padding on the plot column so the fixed-width image fits + # the cell content box exactly (default 5pt L/R padding would overflow it) + flextable::padding(j = "ggplot", padding.left = 0, padding.right = 0, part = "all") |> + flextable::width(j = "ggplot", width = ggplot_col_width) |> + flextable::valign(valign = "bottom", part = "body") } out diff --git a/inst/WORDLIST b/inst/WORDLIST index bf74d5b79..7cd9efaa7 100644 --- a/inst/WORDLIST +++ b/inst/WORDLIST @@ -1,12 +1,27 @@ -ADaM ADEX ADSL +ADaM AE AEs -analyte ARD ARDs -autofit +GDSR +HLT +Hoffmann +Kaplan +MMRM +Ns +ORCID +PY +Pharmacokinetic +Pharmacokinetics +RMP +RMPT +RStudio +Rua +SOCs +Tidyverse +analyte breslow cardx custiomization @@ -17,41 +32,24 @@ efron fleming flextable funder -GDSR gehan ggplot gtsummary harrington -HLT -Hoffmann -Kaplan lineplot lineplots -MMRM -Ns -ORCID peto pharma -Pharmacokinetic -Pharmacokinetics pre prentice -PY quosure quosures -reflow responder rlang's -RMP -RMPT -RStudio -Rua -SOCs survfit tarone tbl tidyselect -Tidyverse unpooled unstratified wilcoxon diff --git a/tests/testthat/test-add_forest.R b/tests/testthat/test-add_forest.R index a1ba4d436..ff72db1a3 100644 --- a/tests/testthat/test-add_forest.R +++ b/tests/testthat/test-add_forest.R @@ -46,12 +46,13 @@ test_that("add_forest(table_engine = 'flextable') works", { NA ) - # autofit layout + 100% preferred width lets Word reflow the wide table to - # the page ("AutoFit to Window") instead of spilling off the page in docx - # output. `layout = "autofit"` alone keeps a 0% preferred width ("AutoFit to - # Contents") and still overflows (#270). - expect_identical(forest_ft$properties$layout, "autofit") - expect_identical(forest_ft$properties$width, 1) + # The plot column has a fixed width and holds an image of exactly that width. + # The default 5pt horizontal cell padding would push the image past the column + # and overflow the page in docx; zeroing it makes the image fit the cell + # content box exactly so the table stays on the page (#270). + gg <- which(forest_ft$col_keys == "ggplot") + expect_identical(unique(forest_ft$body$styles$pars$padding.left$data[, gg]), 0) + expect_identical(unique(forest_ft$body$styles$pars$padding.right$data[, gg]), 0) }) test_that("add_forest handles extreme limits and character NA p-values safely", {