Add save_flex_docx() to save gtsummary tables and flextables to Word#2437
Merged
Conversation
Add as_flex_word() to write a gtsummary table to a Word (.docx) file via flextable, with the table caption optionally placed in the page header and footnotes/source notes/abbreviations in the page footer. The page and page_location arguments add a page-number line to a chosen header/footer region. tbl_split objects are accepted, writing each split table to its own Word section and page. Co-authored-by: Ona <no-reply@ona.com>
Co-authored-by: Ona <no-reply@ona.com>
The Word header/footer regions (caption, footnotes, source notes,
abbreviations, and the page-number line) rendered in the Word template
default font (Cambria) while the flextable body used its own default,
producing a font mismatch. Resolve the flextable body font via
get_flextable_defaults() and apply it (family and size) to every
header/footer run, including the {PAGE}/{NUMPAGES} field runs.
Co-authored-by: Ona <no-reply@ona.com>
Add three ways to customize the Word output: - addl_cmds: a list of flextable command expressions inserted into the call list from as_flex_table(return_calls = TRUE) before evaluation. Named entries insert after the matching call; unnamed entries are appended. Applied after the as_flex_table-lst:addl_cmds theme commands. - header_style / footer_style: named officer::fp_text() property lists that style the Word header and footer regions separately. Each region resolves as base body font -> theme element -> argument (argument wins), merged via update.fp_text so unspecified properties are inherited. The page-number line follows its region's resolved style. - New theme elements as_flex_word-lst:header_style and as_flex_word-lst:footer_style backing the styling arguments. Applies to both single gtsummary tables and tbl_split objects. Co-authored-by: Ona <no-reply@ona.com>
…rd() Each Word region now inherits the styling applied to the corresponding flextable part, so e.g. flextable::fontsize(size = 6, part = "footer") yields a size-6 Word footer. Precedence is body font < theme style < extracted part font < argument style; header_style/footer_style still win and the theme elements apply only when the part carries no styling. The Word header font size follows the body font unless the header part size is explicitly changed, since as_flex_table() always bakes a fixed header size. Sub-family properties (hansi/cs/eastasia) are collapsed onto the extracted font.family to avoid mismatched ascii/hAnsi Word runs. Also filter removed/replaced footnotes in .flex_word_footer_lines() so remove_footnote_*() no longer leaks spurious NA lines into the footer. Co-authored-by: Ona <no-reply@ona.com>
Rename the exported function, its theme elements (as_flex_word-lst:* -> save_flex_docx-lst:*), internal helpers, tests, docs, and the pkgdown reference entry. Regenerate R/sysdata.rda from the theme-elements CSV and man/ via roxygen. Co-authored-by: Ona <no-reply@ona.com>
Each table's section already ends with a "nextPage" section break, which starts the following section on a new page. The additional explicit body_add_break() therefore inserted an extra blank page between tables. Remove the explicit page break and rely on the section break for pagination. Co-authored-by: Ona <no-reply@ona.com>
body_end_block_section() appends a trailing empty paragraph and a closing section, so ending the last table that way rendered an extra blank page. Close sections for all tables except the last with a block section, and set the last table's header/footer as the document's default section via body_set_default_section(), which adds no trailing paragraph/section. Co-authored-by: Ona <no-reply@ona.com>
…_flex_docx() .flex_docx_footer_lines() filtered footnote removals/replacements but did not evaluate a body footnote's `rows` predicate. For tbl_split_by_rows(), a footnote scoped to rows absent from a section still appeared in that section's Word footer (e.g. "2 my label" on a page without the referenced row). Evaluate the `rows` predicate against the table body and drop footnotes matching no rows, mirroring as_flex_table(). Co-authored-by: Ona <no-reply@ona.com>
Generalize save_flex_docx() to also accept a flextable object or a plain list of flextables, in addition to gtsummary tables and tbl_split objects. For a flextable, the caption is relocated to the Word header and the footer part to the Word footer, matching the gtsummary behavior. Remove the include/addl_cmds arguments (handle upstream) in favor of passing a pre-built flextable. Co-authored-by: Ona <no-reply@ona.com>
Add a pr_section argument (and matching save_flex_docx-lst:pr_section theme element) accepting an officer::prop_section() to control page margins, page size, orientation, and section columns. The header/footer regions remain managed by save_flex_docx() (relocated caption/notes), so any header_default/footer_default on pr_section are ignored. For collections the same section is applied to every table with the paging type fixed to 'nextPage' to avoid blank pages. The argument overrides the theme element. Co-authored-by: Ona <no-reply@ona.com>
9 tasks
Add pr_section for fine-grained Word section control in save_flex_docx()
Word header/footer regions already inherit the styling of the corresponding flextable part (e.g. flextable::fontsize(size = 6, part = 'footer') yields a size-6 Word footer), so the explicit header_style/footer_style arguments and their paired save_flex_docx-lst:header_style / save_flex_docx-lst:footer_style theme elements are redundant. Users style the header/footer by styling the flextable parts before saving. The body-font base and part-font inheritance are unchanged. Co-authored-by: Ona <no-reply@ona.com>
Add a pr_section argument (and matching save_flex_docx-lst:pr_section theme element) accepting an officer::prop_section() to control page margins, page size, orientation, and section columns. The header/footer regions remain managed by save_flex_docx() (relocated caption/notes), so any header_default/footer_default on pr_section are ignored. For collections the same section is applied to every table with the paging type fixed to 'nextPage' to avoid blank pages. The argument overrides the theme element. Co-authored-by: Ona <no-reply@ona.com>
a98401e to
821c33f
Compare
…to feat/as_flex_word
Co-authored-by: Ona <no-reply@ona.com>
Co-authored-by: Ona <no-reply@ona.com>
The header/footer defaults changed to FALSE; these tests relied on the old TRUE defaults to relocate content into the Word header/footer regions. Co-authored-by: Ona <no-reply@ona.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What changes are proposed in this pull request?
Added
save_flex_docx()to save a gtsummary table or a flextable to a Word (.docx) file via flextable. Theheaderandfooterarguments (both defaultFALSE) optionally place the table caption in the Word document's page header and the footnotes, source notes, and abbreviations in the page footer; whenFALSE, that content is rendered as part of the table. Thepageandpage_locationarguments add a page-number line (e.g."Page {PAGE} of {NUMPAGES}") to a chosen header/footer region and alignment. A collection of tables is also accepted—atbl_splitobject (fromtbl_split_by_rows()/tbl_split_by_columns()) or a plain list of flextables—writing each table to its own Word section and page. Thepr_sectionargument accepts anofficer::prop_section()for fine-grained control of the Word section (page margins, size, orientation, columns).If there is an GitHub issue associated with this pull request, please provide link.
None.
Summary of changes
save_flex_docx()— writes a gtsummary table or a flextable to a Word.docxfile via flextable.gtsummarytable, atbl_splitobject, aflextable, or a plain list of flextables.header/footerarguments (defaultFALSE) — optionally place the table caption in the Word page header and the footnotes, source notes, and abbreviations in the page footer. WhenFALSE(the default), that content is rendered as part of the table. When relocated, in-cell footnote reference symbols are retained and only the footnote text is moved. For a flextable, the caption (flextable::set_caption()) is relocated to the Word header and the footer part (flextable::add_footer_lines()) to the Word footer.page/page_locationarguments — add a page-number line (e.g."Page {PAGE} of {NUMPAGES}") to a chosen header/footer region and alignment.tbl_splitobject or a plain list of flextables writes each table to its own Word section and page.pr_sectionargument (andsave_flex_docx-lst:pr_sectiontheme element) — accepts anofficer::prop_section()object for fine-grained control of the Word section (page margins, page size, orientation, columns), while the header/footer regions remain managed bysave_flex_docx(); for a collection the same section is applied to every table with the pagingtypefixed to"nextPage".flextable::fontsize(size = 6, part = "footer")yields a size-6 Word footer).tests/testthat/test-save_flex_docx.R, including thetbl_split/list,pr_section, and page-line paths (skips whenflextable/officerare unavailable).NEWS.mdbullet added;NAMESPACE,man/save_flex_docx.Rd, and the pkgdown reference index regenerated/updated.Reviewer Checklist (if item does not apply, mark is as complete)
pkgdown::build_site(). Check the R console for errors, and review the rendered website.devtools::test_coverage()usethis::use_spell_check()runs with no spelling errors in documentationWhen the branch is ready to be merged into master:
NEWS.mdwith the changes from this pull request under the heading "# gtsummary (development version)". If there is an issue associated with the pull request, reference it in parentheses at the end update (seeNEWS.mdfor examples).usethis::use_version(which = "dev")usethis::use_spell_check()again