用 R 批量生成制式化的 Word 文档
楚新元 / 2021-09-24
类似这样的批量生成简历、准考证、证明之类的 Word 文档,MS Office 玩家一般的做法是利用邮件合并功能或者 VBA 实现,对于 R 玩家来说必然是用 R 实现了,暂时没有发现比我这个方法更优雅的方法了。这里以批量生成复工证明 Word 文档为例。
安装公文字体
为了保证最终生成的 Word 文档字体符合公文要求,首先你需要在自己的电脑上安装必要的公文字体,如方正小标宋_GBK(有的单位是方正小标宋)和仿宋_GB2312等。安装公文字体不是本文重点,此处从略。
定义一个 Word 模板
最好是先通过 R Markdown 生成一个 Word 文档,然后在此基础上修改,当然如果通过 R Markdown 默认生成的 Word 文档要是能满足您的要求,不修改也可以,为了充分挖掘 R Markdown 的潜能,自然是各种个性化的修改了(注意:设置模板不要用开始菜单下的那一堆工具按钮,而要在样式和格式里修改。为了保证普适性,建议在 Microsoft Word 下设置模板格式。)。这里是我修改好的一个符合公文要求的模板供参考。
模板下载:https://cxy.cc/source/template.docx
R Markdown 文档参数化设置
主要是把每份复工证明 Word 文档的不同的地方用参数来表示,比如姓名、身份证和家庭住址,就像填空题一样,方便批量生成。参数化设置后的 R Markdown 文档示例代码如下:
---
title: "复工证明"
author: '`r ftext("")`' # 标题下面空一行
output:
officedown::rdocx_document:
reference_docx: template.docx # 模板用来控制字体、段落对齐、间距、缩进
page_margins:
top: 1.458 # 页边距(上37)
bottom: 1.380 # 页边距(下35)
left: 1.063 # 页边距(左27)
right: 1.063 # 页边距(右27)
gutter: 0.00 # 设置装订线
---
西域天竺国:
兹有大唐天子圣谕,`r name`同志,身份证`r ID`,系我天朝`r address`子民,根据我天朝复工要求,该同志在防疫管控期间需要保护唐僧赴西天大雷音寺取经,在满足疫情防控要求的情况下请贵国予以放行为盼。
特此说明。
```{r echo=FALSE}
ftext("") # 附件和中文之间空1行
```
附件:`r name`同志身份证复印件
```{r echo=FALSE}
ftext("") # 这里落款前空第1行
```
```{r echo=FALSE}
ftext("") # 这里落款前空第2行
```
```{r echo=FALSE}
ftext("") # 这里落款前空第3行
```
```{r echo=FALSE}
dpmt = "大唐天子李世民"
date = as.Date(Sys.Date())
year = as.integer(format(date, '%Y'))
month = as.integer(format(date, '%m'))
day = as.integer(format(date, '%d'))
trdate = paste0(year, "年", month, "月", day, "日")
# 计算落款日期前的空格数
date_w = nchar(trdate, type = "width") + 2 # 实际长度要多占用两个字符
date_sp = 54 - 12 - date_w
# 计算落款单位前的空格数
dpmt_w = nchar(dpmt, type = "width")
dpmt_sp = round(54 - 12 - date_w + (date_w - dpmt_w) / 2 + 0.01, 0)
```
`r ftext(strrep(" ", dpmt_sp))`
`r ftext(dpmt)`
`r ftext(strrep(" ", date_sp))`
`r ftext(trdate)`
收集数据,批量生成 Word 文档
先把上面的参数化的 R Markdown 文档保存,例如命名为 report.Rmd
,然后将 template.docx
文件和 report.Rmd
文件放在同一个 R 项目下,我们现在只需要收集所有需要开证明人的姓名、身份证和家庭住址信息(数据可以放在代码里,为了便于管理,最好存放在文件中然后读进来),然后批量渲染这个 report.Rmd
文档即可。源代码如下:
# 加载相关 R 包
library(rmarkdown)
library(purrr)
library(officer)
# 编写函数
gendocx = \(name, ID, address) {
render(
input = "report.Rmd",
output_file = paste0(name, "复工证明.docx")
)
}
# 准备数据
data = data.frame(
name = c("孙悟空", "猪悟能", "沙悟净"),
ID = c("001", "002", "003"),
address = c("花果山水帘洞", "高老庄", "流沙河")
)
# 批量生成
pwalk(data, gendocx)
运行上述代码后就会生成 3 个包含姓名命名的 Word 文档,如“孙悟空复工证明.docx”。需要批量生成复工证明的如果只有这 3 个人,我也就懒得去写代码了,但是随着需要开证明人数的增加你一定会发现用代码生成才是正道,您仅仅需要维护一份包含姓名、身份证和家庭住址的文档即可,重复性的工作交给计算机。另外代码生成的结果您认为还需要再复核一遍吗?R 绝对是你可信赖的靠谱厮。
最后,我要隆重感谢张敬信老师提供的思路和全程技术指导。