---
title: 是莽撞人就来单挑：从 R Markdown 到微软 Office 输出
date: '2017-04-04'
slug: r-markdown-office
---

常年来我有两个非常难达到的目标：一个是邮件清零，另一个是浏览器标签页清零。这两个数字都不大，大约都在 40 左右。难以清零是因为里面有一些不是三两天就能搞定的想法，但我又觉得这些想法很有价值。拖着拖着一年两年过去了也不会有任何动作，感觉人都要爆炸了，所以即日起干脆列举一些出来，然后把邮件归档、浏览器标签页关掉，要是有哪些莽撞人有意去实现它们最好，没有也就算了，等我猴年马月有闲心的时候再来解决它们。

[莽撞人](https://zh.wikipedia.org/wiki/%E5%85%AB%E6%89%87%E5%B1%8F)是听郭德纲相声听来的。平时我喜欢用“壮士”称呼厉害的人。想起“莽撞人”是因为上次大为同志[一口气解决掉 32 篇文章](https://github.com/cosname/cosx.org/issues/4)，我立刻觉得这是个莽撞人，比普通壮士还厉害。

好了，说第一个想法。很久以前我注意到了 [ReporteRs](http://davidgohel.github.io/ReporteRs/) 这个包，用来从 R 生成 Office 文档，如 Word 和 PowerPoint。我感觉从细节上来说，它比 Pandoc 更灵活一些，主要是因为 Pandoc 的 Markdown 能生成的元素有限，这是它的优点（强制简化你的写作），但有时候也是缺点，尤其是被 Office 毒害了大脑的用户们，总是想这里几个字涂红，那里画个表格，表格还要合并单元格，这些用户随便提个要求 Markdown 都很难满足。

对我个人而言，我压根儿不在乎这些多余的功能，我就喜欢在强约束条件下写作，免得我老是分心注意排版的事情，但问题是，Office 用户就像[白绝](https://zh.wikipedia.org/wiki/%E7%B5%95)一样乌泱乌泱的，所以三天两头就会被人问 Word 支持的问题，而且这些用户通常也不能接受强约束条件。最后一根稻草是一次芒果的博客[赤果果挑衅](http://www.mango-solutions.com/wp/2016/10/why-i-would-rather-use-reporters-than-rmarkdown/)我大 knitr 和 R Markdown，说你家的 Word 算啥 Word。

好嘛，且待我有空用键盘收拾你。然而我没空。只好先用嘴遁。

我的天，真的会有人用 ReporteRs 写 Word 文档咩？我的意思是，一个 Word 文档竟然是靠 R 函数一句一句写出来的。这特特么是不是也太反人类了。要写一个文档，操起键盘就开始写标题、作者、日期、正文段落、章节、图表等等就好了啊，肿么是从 `doc = addTitle()` 开始呢。

我的想法是，既然 ReporteRs 的基础设施看起来比较完备，那么我们能不能给它做一个包装：外壳用 R Markdown，底层用 ReporteRs 里的函数。这个想法有至少两种可能的实现方式：

1. R Markdown 通过 knitr 转 Markdown，然后 Pandoc 介入，首先将 Markdown 翻译为 JSON 或其它结构化数据，然后把里面的元素一项一项传入合适的 ReporteRs 函数，生成一个大 R 脚本（脚本里包含 `addTitle()` 这样的 R 语句），最后通过运行这个脚本生成 Office 文档。

1. R Markdown 到 Markdown 到 HTML，解析 HTML 文件，再动态生成 ReporteRs 语句。

后一种方式的优点是可以利用 bookdown 里一些现成的功能，比如图表编号和交叉引用，缺点是 HTML 的结构化程度可能不如 JSON，翻译 ReporteRs 语句的时候可能会困难一些。

关键的一个难点是如果别人修改了 Office 文档，如何把这些修改导回 R Markdown 里。不解决这个问题，也无法回应芒果的无情吐槽。

当然我也不是有十足的把握这两条路能行得通，里面肯定还有很多细节问题需要考虑，我对 ReporteRs 的文档也不是完全熟悉。要是信了我的话，掉进大坑浪费了时间请莫怪我。

最后吐槽一下 ReporteRs 这个包名：通常我写一篇两千字的日志完全不会觉得手酸，但今天写这篇短日志却让我的左手小指感觉好酸。我早年的时候也有这个倾向，喜欢把包名里的 R 大写，如 formatR，后来基本上只用纯小写的名字了。一个包名开头要按一次 Shift 键，然后哗啦啦敲几个字母，正中间急停，再按一次 Shift 键，然后又是小写。就问你想不想掀桌。
