如何进一步微调gtsummary分页RTF输出:智能分页与列宽控制
gtsummary RTF分页优化:解决手动调整与宽度不一致问题
我已基于此前方案实现gtsummary包RTF输出的分页,每页可重复标题与脚注,但遇到两个待解决问题:
- 需手动调整页面大小与行数,否则内容会错误跨页,能否智能确保拆分对象在新页完整展示,无需手动调整?
- 拆分后各页面的表格宽度不一致,是否有简便方法统一控制?
当前实现代码
library(dplyr) library(gtsummary) library(flextable) # 加载示例数据集 adsl <- pharmaverseadam::adsl adae <- pharmaverseadam::adae # 数据预处理 -------------------------------------------- adae <- adae %>% dplyr::filter( # 筛选安全人群 SAFFL == "Y" ) # 创建层级表格 tbl <- adae |> tbl_hierarchical( variables = c(AESOC, AEDECOD), by = ARM, id = USUBJID, denominator = adsl, overall_row = TRUE, label = "..ard_hierarchical_overall.." ~ "Any Adverse Events" ) # 手动拆分表格为小片段 tbl_split <- tbl_split_by_rows(tbl, row_numbers = seq(10, nrow(tbl), by = 10)) # 将每个拆分表格转为flextable flextables <- lapply(seq_along(tbl_split), function(i) { tbl_split[[i]] |> as_flex_table() |> add_header_lines(as_paragraph(as_chunk( paste0("Table 15.3: AE by SOC/PT"), props = fp_text_default(font.family = "San Serif", font.size = 12)) )) |> autofit()|> paginate(init = TRUE, hdr_ftr = TRUE) # 初始化分页 }) # 合并为命名列表 flextable_list <- setNames(flextables, paste0("Page_", seq_along(flextables))) flextable_list <- flextables # 定义RTF格式的章节属性(带分页符) sect_properties <- officer::prop_section( page_size = officer::page_size(orient = "landscape", width = 20, height = 8), page_margins = officer::page_mar(top = 1, bottom = 1, left = 1, right = 1), type = "nextPage" # 确保章节间分页 ) # 保存所有flextable到RTF do.call( flextable::save_as_rtf, c(flextable_list, list(path = "tbl.rtf", pr_section = sect_properties)) )
解决方案
问题1:智能分页,无需手动调整页面参数
放弃手动拆分表格的方式,改用flextable原生的自动分页功能,同时设置规则保证层级行(如AESOC分组行)不被拆分到两页,结合标准页面尺寸让系统自动计算每页容纳行数。
修改后核心代码:
# 直接将gtsummary表格转为flextable并配置自动分页 tbl_flex <- tbl |> as_flex_table() |> add_header_lines(as_paragraph(as_chunk( "Table 15.3: AE by SOC/PT", props = fp_text_default(font.family = "San Serif", font.size = 12) ))) |> # 设置表格自适应布局 set_table_properties(layout = "autofit") |> # 关键:配置分页规则,禁止在层级分组行(AESOC行)处拆分 paginate( init = TRUE, hdr_ftr = TRUE, # 每页保留标题和脚注 split = selector$selector( # 假设非缩进行是AESOC分组行,缩进行是AEDECOD明细行,根据实际标签格式调整 i = ~ !grepl("^ ", label), split = "never" ) ) # 使用标准A4横向页面属性 sect_properties <- officer::prop_section( page_size = officer::page_size(orient = "landscape", width = 21.6, height = 15.2), page_margins = officer::page_mar(top = 1, bottom = 1, left = 1, right = 1) ) # 保存自动分页后的RTF save_as_rtf(tbl_flex, path = "tbl_auto_paginate.rtf", pr_section = sect_properties)
说明:selector中的规则需要匹配你的表格行标签格式——如果分组行(如AESOC)没有缩进,明细行(如AEDECOD)有2个空格缩进,就用~ !grepl("^ ", label)选中分组行,禁止在这些行中间拆分页面,保证层级完整。
问题2:统一各页面表格宽度
通过固定表格整体宽度或指定列宽的方式,避免autofit()在不同页面计算出不同宽度,有两种简便方法:
方法1:固定表格占满页面宽度
tbl_flex <- tbl |> as_flex_table() |> add_header_lines(...) |> # 设置表格宽度为页面可用宽度的100%,采用固定布局 set_table_properties(width = 1, layout = "fixed") |> # 可手动指定某列宽度,其余列自动分配剩余空间 width(j = 1, width = 3) |> paginate(...)
方法2:统一分配所有列宽度
# 获取表格列数,平均分配页面可用宽度 col_count <- ncol(tbl$table_body) # 页面可用宽度=总宽度-左右边距=21.6-1-1=19.6,这里取19方便计算 tbl_flex <- tbl |> as_flex_table() |> add_header_lines(...) |> # 所有列平均分配宽度 width(j = 1:col_count, width = 19/col_count) |> paginate(...)
内容的提问来源于stack exchange,提问作者xiecheng gu
相关产品推荐
相关产品推荐

