1 课程回顾 🔗
通过上节课,我们学习了如何升级 Emacs 的插件,以及遇到报错应该如何处理。
今天我们来学习 Emacs 里的表格。
2 概述 🔗
Emacs 里是否可以处理表格?当然可以。尤其是 Org-mode,被称为文本界的 Office 套件,必须可以处理表格。今天我们来学习 Emacs 里的表格。
今天的主要内容有:
- 创建表格
- 导出表格
- 表格公式
3 Emacs里的表格 🔗
3.1 table.el 🔗
Emacs 自带 table.el
包,可以处理纯文本表格,比如我们可以通过 table-insert
命令在当前光标处插入一个表格:
我们可以通过 <TAB>
键在不同的单元格里移动和编辑。
如果要使用这个包,需要注意以下几点:
- 你需要使用等宽字体,或调整好你的中英文字体大小比例,这样不至于表格会错乱不对齐
- 插入的表格,不依赖于文件格式,在任何缓冲区都可以插入,可以理解为类似于像 ASCII 艺术的那种感觉
- table.el 更关注的是文本表格的视觉布局和组织,不支持公式等复杂功能
3.2 org-table.el 🔗
下面讲一讲更加实用的 org-table.el
包,这个包是 Org-mode 官方支持的表格功能,它几乎能做到 Office 里做到的事,区别在于它是基于纯文本的,而 Office 不是。
你问我?我当然更加喜欢基于纯文本的 Org-mode,如果不是要和其他人协作,我甚至可能会卸载 Office。
下面就简单讲一讲 Org-mode 里的表格操作。
3.2.1 表格基本操作 🔗
3.2.1.1 创建表格 🔗
我自己创建表格用的是 yasnippet
的模板,只需要输入 <ta
再按下 <tab>
键,Emacs 就会自动在 Org 文档里创建一个表格:
这个 yasnippet 的模板如下:
# -*- mode: snippet -*-
# name: table
# key: <ta
# --
#+CAPTION: $1
#+NAME: ${1:tablename}
#+ATTR_LATEX: :float nil :environment tabularx :width \textwidth :align
| ${2:key} | ${3:description} |
|-$0
3.2.1.2 表格的编辑 🔗
我自己常用的表格编辑动作如下,供参考:
快捷键 | 函数 | 作用 |
---|---|---|
<tab> | org-cycle | 进入下一个单元格,同时可以自动调整表格格式 |
<backtab> | org-shifttab | 进入上一个单元格,同时可以自动调整表格格式 |
C-c C-c | org-ctrl-c-ctrl-c | 自动调整表格格式 |
RET | org-return | 进入下一行 |
C-c RET | org-ctrl-c-ret | 在当前行下加一行分隔线和新行然后移动到新行 |
C-c - | org-ctrl-c-minus | 在当前行下加一行分隔线 |
M-up | org-metaup | 交换当前行和上一行 |
M-down | org-metadown | 交换当前行和下一行 |
M-left | org-metaleft | 交行当前列和左边一列 |
M-right | org-metaright | 交换当前列和右边一列 |
M-S-up | org-shiftmetaup | 删除当前行 |
M-S-down | org-shiftmetadown | 在当前位置新增空行并将当前行下移一行 |
M-S-left | org-shiftmetaleft | 删除当前列 |
M-S-right | org-shiftmetaright | 在当前位置新增空列并将当前列右移一列 |
org-table-blank-field | 清空当前单元格 | |
M-a | org-backward-sentence | 跳转到当前单元格首 |
M-e | org-forward-sentence | 跳转到当前单元格尾 |
C-<tab> | org-ctrl-c-tab | 折叠或展开当前列 |
C-c ' | org-edit-special | 在一个新buffer输入表格公式 |
C-c = | org-table-eval-formula | 在当前单元格输入公式 |
C-c * | org-ctrl-c-star | 重新按照公式计算和更新表格 |
C-c } | org-table-toggle-coordinate-overlays | 是否显示表格的参考线更便于编写公式 |
3.2.2 表格公式 🔗
下面着重说下Org mode里表格的公式。
3.2.2.1 如何引用行、列、分隔线和单元格 🔗
- 行
- 用
@#
来表示第几行:如@1
表示第一行,@0
表示当前行 - 用
@>
来表示最后一行 - 用
@<
来表示第一行 - 用
@+3
来表示当前行后3行:@-2
表示当前行前2行
- 用
- 列
- 用
$数字
来表示第几列:如$1
表示第一列,$0
表示当前列 - 用
$>
来表示最后一列 - 用
$<
来表示第一列 - 用
$+3
来表示当前列后3列:$-2
表示当前列前2列
- 用
- 单元格
- 用
@#$#
来表示第几行第几列的单元格,如@2$3
表示第二行第三列 - 用
@0$0
表示当前单元格
- 用
- 分隔线
- 用
@I
表示第一个水平分隔线,用@II
表示第二个,@III
表示第三个 - 用
@-I
表示在当前行上一个水平分隔线,@+I
表示当前行下一个水平分隔线 - 用
@III+2
表示在第三个水平分隔线后2行
- 用
- 范围
- 用
..
表示范围,如@2..@>
表示第2行到最后一行
- 用
- 结果的格式
- 用
;xx
来表示结果的格式规定,如;%.1f
表示保留到小数点后1位
- 用
3.2.2.2 常用例子 🔗
Org-mode 的表格支持两种公式,我们先讲 calc 格式或 elisp 的代码公式,我们可以根据需要灵活运用。
3.2.2.2.1 求平均 🔗
假设我们的原始表格如下:
年份 | 销售额 |
---|---|
2020 | 135 |
2021 | 150 |
2022 | 175 |
2023 | 160 |
平均 |
那么我们如何来写这个公式呢,我们可以将光标放到总计对应的那个空单元格,然后按下 C-c '
后编辑公式: @>$2=vmean(@I$2..@II$2)
,
编辑完后,表格就变成了如下:
| 年份 | 销售额 |
|------+--------|
| 2020 | 135 |
| 2021 | 150 |
| 2022 | 175 |
| 2023 | 160 |
|------+--------|
| 平均 | |
#+TBLFM: @>$2=vmean(@2$2..@5$2);%.1f
我们可以使用
;%.1f
来表示公式计算后的格式,如这个代表精确到小数点后一位。
然后我们在最后一个单元格里按下 C-c *
(或将光标移动到公式行按 C-c C-c
) 就可以得到最终结果了:
年份 | 销售额 |
---|---|
2020 | 135 |
2021 | 150 |
2022 | 175 |
2023 | 160 |
平均 | 155.0 |
3.2.2.2.2 求和 🔗
还是针对上面的表格,求和的公式为 @>$2=vsum(@I$2..@II$2)
最终的结果为:
年份 | 销售额 |
---|---|
2020 | 135 |
2021 | 150 |
2022 | 175 |
2023 | 160 |
平均 | 620 |
3.2.2.2.3 单元格拼接 🔗
针对上面那个表格,如果我们想要增加一列,新的列由左边两列拼接而来,如 2020年的销售额为135万
,此时编辑公式为 (concat $1 "年的销售额为" $2 "万")
最终的结果为:
年份 | 销售额 | 新的文本 |
---|---|---|
2020 | 135 | 2020年的销售额为135万 |
2021 | 150 | 2021年的销售额为150万 |
2022 | 175 | 2022年的销售额为175万 |
2023 | 160 | 2023年的销售额为160万 |
3.2.2.2.4 多个公式 🔗
如果有多个公式,在 #+TBLFM:
的公式一行,通过 ::
将多个公式连接起来,如下:
| 年份 | 销售额 | 拼接的文本 |
|------+--------+-------------|
| 2020 | 160 | 2020年160万 |
| 2021 | 150 | 2021年150万 |
| 2022 | 175 | 2022年175万 |
| 2023 | 160 | 2023年160万 |
|------+--------+-------------|
| 平均 | 161.25 | |
| 总计 | 645 | |
#+TBLFM: @>>$2=vmean(@I$2..@II$2)::@>$2=vsum(@I$2..@II$2)::@2$3..@5$3='(concat $1 "年" $2 "万")
基本上学会上面这些常用的公式,能解决日常工作的大部分问题了,如果还有别的诉求,可以详细阅读 Org-mode 的官方文档。
3.2.3 列表表格 🔗
我们在日常工作中,还会遇到一个诉求,就是更加复杂的表格,例如:
- 在一个单元格里放一张图片
- 在一个单元格里放一些项目符号
- 在一个单元格里放多个段落文本
- …
上述诉求,用常规的 org-table.el
是无法实现的,此时,我们需要 org-mode-ox-odt 这个包的帮助。
3.2.3.1 安装配置 🔗
(add-to-list 'package-archives
'("ox-odt" . "https://kjambunathan.github.io/elpa/"))
(use-package ox-odt
:ensure t
:after (org ox ox-html)
:init
(add-to-list
'org-export-filter-parse-tree-functions
(defun org-html--translate-list-tables (tree backend info)
(if (member backend '(html latex))
(org-odt--translate-list-tables tree backend info)
tree)))
)
3.2.3.2 如何使用 🔗
安装完这个包后,我们就可以通过 list table
(列表表格)来构建复杂的表格了。下面是一个示例:
#+CAPTION: 示例列表表格
#+NAME: 示例列表表格
#+ATTR_ODT: :list-table t
-
- 标题1
- 标题2
- 标题3
- ----------------
- 2007
-
- 很好
- 非常好
- 特别好
-
- [ ] 待办1
- [ ] 待办2
- [ ] 待办3
- ---------------
-
噼里啪啦第一段话
噼里啪啦第二段话
-
[[https://orgmode.org/resources/img/org-mode-unicorn.svg]]
-
| 标题1 | 标题2 |
|-------+-----------|
| 2008 | good |
| 2010 | wonderful |
然后在我们按下 C-c C-e
选择 html
的格式进行导出的时候,可以看到这个复杂表格已经按照我们的预期生成了:
4 结语 🔗
通过今天的学习,我们了解了在 Emacs/Org-mdoe 内的表格,我们了解到如何在 Org-mode 里处理复杂一点的表格,如何使用公式,如何通过列表表格来生成更加复杂的表格,Org-mode 简直就是纯文本界的 Office!
这节课的配置文件的快照见:emacs-config-l34.org
你也可以在 这里 查看最新的配置文件。