knitr/Rmd: 转换为 MS Word 时添加标题页和文本
knitr/Rmd: Adding title page and text when converting to MS Word
我正在尝试使用 rmarkdown
包编写报告,不幸的是,我的现场报告通常以 MS Word 文档的形式提交。所以我不能总是依赖 LaTeX
的强大功能并且必须能够将我的 .Rmd 转换为 MS Word。现在,因为我希望能够从同一个源文件创建 PDF 和 MS Word 文件,所以我试图找到一种通用的方法来执行此操作。我已经使用 apa6
LaTeX-document class 使 PDF 正常工作。创建 Word 文件时,.Rmd 看起来像这样:
---
title: My title
abstract: This is the abstract.
author: John Doe
affiliation: Unknown
note: Nothing to say.
output:
word_document:
reference_docx: myreference.docx
---
Lorem ipsum.
我可以从中创建一个 Word 文档,但由于显而易见的原因,我的自定义 yaml
-变量(例如摘要)不会在文档中呈现。
基本上,我的问题如下:
在创建word文档时,如何在文档前添加一个扉页(包括作者姓名、单位、作者注释等)和另一页只有摘要body("Lorem ipsum")?这里的重点不是创建分页符(还有其他 open questions on this),而是**有没有办法让 pandoc
使用自定义 yaml
变量将它们放在记录并为它们指定样式?
rmarkdown
包提供了一个 include()
功能,但它只适用于 HTML 和 PDF 文档。
我发现可以自定义 rmarkdown
生成的 Markdown 文件的内容(例如添加和修改标题页),然后再将其提交给 pandoc
以转换为 DOCX
通过使用预处理器。假设我们正尝试在摘要之前添加 YAML 参数 note
中指定的一些信息(同时已将对摘要的支持添加到 pandoc
)。
为此,我们首先需要一个预处理器函数来读取输入文件并解析 YAML front matter,并自定义输入文件:
my_pre_processor <- function(metadata, input_file, runtime, knit_meta, files_dir, output_dir, from) {
# Identify YAML front matter delimiters
input_text <- readLines(input_file, encoding = "UTF-8")
yaml_delimiters <- grep("^(---|\.\.\.)\s*$", input_text)
if(length(yaml_delimiters) >= 2 &&
(yaml_delimiters[2] - yaml_delimiters[1] > 1) &&
grepl("^---\s*$", input_text[yaml_delimiters[1]])) {
yaml_params <- yaml::yaml.load(paste(input_text[(yaml_delimiters[1] + 1):(yaml_delimiters[2] - 1)], collapse = "\n"))
} else yaml_params <- NULL
# Modify title page
custom_lines <- c(
"NOTE:"
, metadata$note
, "\n\n"
, "# Abstract"
, "\n"
, metadata$abstract
, "\n"
)
## Add modified title page components after YAML front matter
augmented_input_text <- c(custom_lines, input_text[(yaml_delimiters[2] + 1):length(input_text)])
# Remove redundant default abstract
yaml_params$abstract <- NULL
# Add modifications to input file
augmented_input_text <- c("---", yaml::as.yaml(yaml_params), "---", augmented_input_text)
input_file_connection <- file(input_file, encoding = "UTF-8")
writeLines(augmented_input_text, input_file_connection)
close(input_file_connection)
NULL
}
现在我们需要定义一个使用预处理器的自定义格式:
my_word_document <- function(...) {
config <- rmarkdown::word_document(...)
# Preprocessor functions are adaptations from the RMarkdown package
# (https://github.com/rstudio/rmarkdown/blob/master/R/pdf_document.R)
pre_processor <- function(metadata, input_file, runtime, knit_meta, files_dir, output_dir, from = .from) {
# save files dir (for generating intermediates)
saved_files_dir <<- files_dir
args <- my_pre_processor(metadata, input_file, runtime, knit_meta, files_dir, output_dir, from)
args
}
config$pre_processor <- pre_processor
config
}
现在,您可以在渲染 R Markdown 文档时使用自定义格式,如下所示:
rmarkdown::render("./foo/bar.Rmd", output_format = my_word_document())
我正在尝试使用 rmarkdown
包编写报告,不幸的是,我的现场报告通常以 MS Word 文档的形式提交。所以我不能总是依赖 LaTeX
的强大功能并且必须能够将我的 .Rmd 转换为 MS Word。现在,因为我希望能够从同一个源文件创建 PDF 和 MS Word 文件,所以我试图找到一种通用的方法来执行此操作。我已经使用 apa6
LaTeX-document class 使 PDF 正常工作。创建 Word 文件时,.Rmd 看起来像这样:
---
title: My title
abstract: This is the abstract.
author: John Doe
affiliation: Unknown
note: Nothing to say.
output:
word_document:
reference_docx: myreference.docx
---
Lorem ipsum.
我可以从中创建一个 Word 文档,但由于显而易见的原因,我的自定义 yaml
-变量(例如摘要)不会在文档中呈现。
基本上,我的问题如下:
在创建word文档时,如何在文档前添加一个扉页(包括作者姓名、单位、作者注释等)和另一页只有摘要body("Lorem ipsum")?这里的重点不是创建分页符(还有其他 open questions on this),而是**有没有办法让 pandoc
使用自定义 yaml
变量将它们放在记录并为它们指定样式?
rmarkdown
包提供了一个 include()
功能,但它只适用于 HTML 和 PDF 文档。
我发现可以自定义 rmarkdown
生成的 Markdown 文件的内容(例如添加和修改标题页),然后再将其提交给 pandoc
以转换为 DOCX
通过使用预处理器。假设我们正尝试在摘要之前添加 YAML 参数 note
中指定的一些信息(同时已将对摘要的支持添加到 pandoc
)。
为此,我们首先需要一个预处理器函数来读取输入文件并解析 YAML front matter,并自定义输入文件:
my_pre_processor <- function(metadata, input_file, runtime, knit_meta, files_dir, output_dir, from) {
# Identify YAML front matter delimiters
input_text <- readLines(input_file, encoding = "UTF-8")
yaml_delimiters <- grep("^(---|\.\.\.)\s*$", input_text)
if(length(yaml_delimiters) >= 2 &&
(yaml_delimiters[2] - yaml_delimiters[1] > 1) &&
grepl("^---\s*$", input_text[yaml_delimiters[1]])) {
yaml_params <- yaml::yaml.load(paste(input_text[(yaml_delimiters[1] + 1):(yaml_delimiters[2] - 1)], collapse = "\n"))
} else yaml_params <- NULL
# Modify title page
custom_lines <- c(
"NOTE:"
, metadata$note
, "\n\n"
, "# Abstract"
, "\n"
, metadata$abstract
, "\n"
)
## Add modified title page components after YAML front matter
augmented_input_text <- c(custom_lines, input_text[(yaml_delimiters[2] + 1):length(input_text)])
# Remove redundant default abstract
yaml_params$abstract <- NULL
# Add modifications to input file
augmented_input_text <- c("---", yaml::as.yaml(yaml_params), "---", augmented_input_text)
input_file_connection <- file(input_file, encoding = "UTF-8")
writeLines(augmented_input_text, input_file_connection)
close(input_file_connection)
NULL
}
现在我们需要定义一个使用预处理器的自定义格式:
my_word_document <- function(...) {
config <- rmarkdown::word_document(...)
# Preprocessor functions are adaptations from the RMarkdown package
# (https://github.com/rstudio/rmarkdown/blob/master/R/pdf_document.R)
pre_processor <- function(metadata, input_file, runtime, knit_meta, files_dir, output_dir, from = .from) {
# save files dir (for generating intermediates)
saved_files_dir <<- files_dir
args <- my_pre_processor(metadata, input_file, runtime, knit_meta, files_dir, output_dir, from)
args
}
config$pre_processor <- pre_processor
config
}
现在,您可以在渲染 R Markdown 文档时使用自定义格式,如下所示:
rmarkdown::render("./foo/bar.Rmd", output_format = my_word_document())