使用R语言officer包实现横竖版交替PDF报告及空白页问题解决
问题:交替横竖版PDF报告生成的页面空白与布局丢失问题
我需要制作一份交替显示竖版(文本内容)和横版(大型图表)的PDF报告,流程是用R的officer包生成.docx文件,再通过Word或LibreOffice转成PDF。但遇到两个问题:
- 报告末尾会多出一页空白竖版页
- 转PDF时,竖版和横版页面之间会出现空白页(Word里能看到页码跳号,比如从1直接到3)
虽然Word端有手动解决办法,但因为要处理数百组横竖交替章节,希望通过officer包直接解决。
最初尝试的代码
library(officer) doc_1 <- read_docx() doc_1 <- body_add_par(doc_1, value = "Portrait") doc_1 <- body_end_block_section(doc_1, block_section(prop_section())) doc_1 <- body_add_par(doc_1, value = "Landscape") doc_1 <- body_end_section_landscape(doc_1) temp <- tempfile(fileext = ".docx") print(doc_1, target = temp) # system(paste0('open "', temp, '"'))
批量迭代时的布局丢失问题
参考David的方案后有所改善,但用body_add_docx批量迭代时,部分竖版布局丢失,相关代码如下:
library(officer) portrait_section_prop <- prop_section(page_size = page_size(orient = "portrait")) landscape_section_prop <- prop_section(page_size = page_size(orient = "landscape")) core <- function(i){ doc_1 <- read_docx() |> body_add_par(value = paste("Portrait", i)) |> body_end_block_section(value = block_section(portrait_section_prop)) |> body_add_par(value = paste("Landscape", i)) |> body_end_block_section(value = block_section(landscape_section_prop)) |> body_set_default_section(landscape_section_prop) return(doc_1) } accu <- core(1) for(i in 2:10){ doc_1 <- core(i) temp <- tempfile(fileext = ".docx") print(doc_1, temp) accu <- body_add_docx(accu, temp) } print(accu, target = tempfile(fileext = ".docx")) |> browseURL()
解决方案
1. 解决初始代码的空白页问题
核心是避免不必要的章节分页,不要在内容末尾额外添加空白章节:
library(officer) doc_1 <- read_docx() # 添加竖版内容(默认竖版章节) doc_1 <- body_add_par(doc_1, value = "Portrait") # 设置横版章节,指定仅在新页面开始,避免多余空白 doc_1 <- body_end_block_section(doc_1, block_section( prop_section( page_size = page_size(orient = "landscape"), type = "nextPage" ) )) # 添加横版内容 doc_1 <- body_add_par(doc_1, value = "Landscape") temp <- tempfile(fileext = ".docx") print(doc_1, target = temp)
2. 解决批量迭代的布局丢失问题
调整子文档的章节设置,合并时确保章节属性衔接正确:
library(officer) # 预定义横竖版章节(指定新页面开始) portrait_section <- block_section(prop_section( page_size = page_size(orient = "portrait"), type = "nextPage" )) landscape_section <- block_section(prop_section( page_size = page_size(orient = "landscape"), type = "nextPage" )) core <- function(i){ # 子文档仅包含完整的横竖交替内容,不设置默认章节 doc <- read_docx() |> body_add_par(value = paste("Portrait", i)) |> body_end_block_section(value = landscape_section) |> body_add_par(value = paste("Landscape", i)) return(doc) } accu <- core(1) for(i in 2:10){ doc_i <- core(i) temp <- tempfile(fileext = ".docx") print(doc_i, temp) # 合并前切换回竖版章节,确保下一个子文档从竖版开始 accu <- body_end_block_section(accu, portrait_section) accu <- body_add_docx(accu, temp) } final_doc <- tempfile(fileext = ".docx") print(accu, target = final_doc) |> browseURL()
关键说明
- 章节类型控制:用
type = "nextPage"确保章节切换仅生成必要的新页面,避免自动空白页; - 避免末尾多余章节:文档最后不要额外设置章节,否则会生成空白页;
- 合并时的章节衔接:每次合并子文档前,确保主文档当前章节与子文档起始章节匹配,避免布局冲突。
内容的提问来源于stack exchange,提问作者Sébastien Wouters
相关产品推荐
相关产品推荐

