You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何进一步微调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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.12 07:54:57