合并单元格

把表格中的多个格子合成一个,也就是 合并单元格,按方向和工具可以清楚区分。横向跨多列使用标准命令 \multicolumn;纵向跨多行使用 multirow 包的 \multirow;二者结合则可以合并一个矩形块。若只是想让一个单元格中的内容分成多行,那并不是合并,而是 makecell 的工作。本页依次介绍这四种工具,并包含对齐方面的常见陷阱。

横向合并 — \multicolumn

\multicolumn 在同一行中合并相邻列。它内置于标准 LaTeX,不需要额外包。其形式是三引数 \multicolumn{n}{spec}{text}n 是跨越的列数,spec 是合并后这个单元格 如何对齐(单列的列指定)text 是内容。例如 \multicolumn{2}{c}{Header} 会把两列合成一个单元格并居中。

关键在于,spec 描述的是“合并后的 1 列”,不会自动继承原来 n 列的指定。因此必须明确写一个 lcrspec 还可以包含 竖线 |@{…},从而 仅对这个合并单元格覆盖 该位置的线条和列间距。如果相邻两个 \multicolumn 中,一个以 | 结束、另一个以 | 开始,只会画一条线,不会重复。

latex
\begin{tabular}{lcc}
  \hline
  \multicolumn{3}{c}{売上集計} \\
  \hline
  項目 & 上期 & 下期 \\
  \hline
  国内 & 120 & 145 \\
  海外 & 80 & 96 \\
  \hline
\end{tabular}

这里第一行用 \multicolumn{3}{c}{Sales summary} 把原本应分成三列的一行折叠成 一个居中单元格,作为整张表的标题。即使是合并行,该行的单元格合计仍然 必须等于声明的列数(这里是 3)。因为 \multicolumn{3}{…} 已经承担了三列,所以这一行不需要 &

还要记住 n 设为 1 的用法。\multicolumn{1}{…}{…} 不跨列,但可以 只覆盖该单元格的对齐方式,或 去掉该位置的竖线 |。例如只想让数字列(r)的表头居中,可写 \multicolumn{1}{c}{Header};在带外框表格中只想去掉某一格的竖线,可写不含 |\multicolumn{1}{c}{…}

纵向合并 — multirow

纵向跨多行的单元格不能用标准命令创建,需要载入 multirow(导言区写 \usepackage{multirow})。核心命令是 \multirow{n}{width}{text}n 是跨越的行数,width 是单元格宽度,text 是内容。宽度传入 * 时,文本按 自然宽度 排版;\multirow{3}{*}{Label} 是最直接的形式。

决定性规则是:\multirow 所跨越的下方行中的对应单元格必须留空。把 \multirow 放在上方行,后续行在同一列位置只写 &,不写内容。如果忘记留空,下方行内容会 叠印\multirow 排出的文字上。正的 n 表示“本行以及下方 n−1 行”,负值表示“本行以及上方 −n−1 行”(官方文档的说法)。

document.tex
\usepackage{multirow}
% ...
\begin{tabular}{|l|l|c|}
  \hline
  \multirow{2}{*}{果物} & りんご & 380 \\
                        & みかん & 120 \\
  \hline
  \multirow{2}{*}{野菜} & 人参   & 90 \\
                        & 大根   & 150 \\
  \hline
\end{tabular}

这里第 1 列中的“Fruit”和“Vegetable”各自纵向跨两行。关键是 \multirow{2}{*}{Fruit} 写在上方行,而下一行第 1 列用 只写 &、不写内容 的方式跳过。由于 width*,标签按自然宽度排版,并在两行的垂直方向居中。

\multirow 还有两个可选参数。开头的 [vpos] 设置垂直对齐(默认居中 c,顶部 t,底部 b)。text 后面的 [vmove]微调用长度,可把文本从原位置向上移动,负值则向下移动。当相对于线条和单元格边界看起来垂直居中略有偏差时,可像 \multirow{3}{*}[2pt]{…} 这样给一个小值调整。注意,如果 width 给绝对值(如 \multirow{2}{4em}{…}),内容会按该宽度的 parbox 排版,长标签会换行。

引数作用备注
[vpos]垂直对齐(可选,开头)默认 c;也可用 t / b
n跨越行数(必需)正值向下,负值向上
width单元格宽度(必需)* 为自然宽度;绝对值会作为 parbox 换行
[vmove]位置微调(可选,在 text 后)正值上移,负值下移

块合并 — 在 \multicolumn 中使用 \multirow

要创建同时跨横向和纵向的 矩形块,需要 组合 \multirow\multicolumn。顺序是固定的:应把 \multirow 放在 \multicolumn 内部。官方文档也以 \multicolumn{2}{c}{\multirow{3}{*}{Multi-multi}} 为例,并明确说明反过来嵌套“will not work”。可以记作:外层 \multicolumn 负责横向跨列,内层 \multirow 负责纵向跨行。

给块周围画线时,不要用横跨整行的 \hline,而应使用 只限于某个列范围的线条,这样不会切穿合并区域。标准工具是 \cline{i-j}(第 i 列到第 j 列);如果使用 booktabs,则是 \cmidrule{i-j}。把合并单元格下方的范围排除在线条之外,就能干净地只勾出块的外形。

document.tex
\usepackage{multirow}
% ...
\begin{tabular}{|l|l|c|}
  \hline
  \multicolumn{2}{|c|}{\multirow{2}{*}{地域・分類}} & 件数 \\
  \multicolumn{2}{|c|}{}                          & \\
  \hline
  東日本 & 関東 & 12 \\
  \cline{1-3}
  西日本 & 関西 & 9 \\
  \hline
\end{tabular}

这里在左上角创建一个 2 列 × 2 行的矩形块。第一行的 \multicolumn{2}{|c|}{\multirow{2}{*}{Region / class}} 合并两列和两行,第二行用空的 \multicolumn{2}{|c|}{} 接住同一位置(因为 \multirow 跨行,下方行的块区域要留空)。\cline{1-3} 用于分隔正文行,而块本身用 \hline 包住上下边。

在一个单元格内换行 — makecell

这里需要区分一点:想让单个单元格分成多行,并不是合并单元格。由于 lcr 列不会自动换行,直接在这类单元格中写 \\ 会出错。如果只是想让短字符串在指定位置换行,最方便的工具是 makecell\makecell{…}\usepackage{makecell})。

\makecell{line1\\line2} 会把内容排成 一个小的一列表格,并用 \\ 进行 强制换行。可选参数可以指定对齐,例如 \makecell[l]{…}(左对齐)、\makecell[t]{…}(顶部),通过 垂直和水平对齐各一个字母 传入(默认两者都居中)。用于表头时,还有带通用字体和间距设置的 \thead{…}

document.tex
\usepackage{makecell}
% ...
\begin{tabular}{lc}
  \hline
  \thead{項目} & \thead{前年比\\(\%)} \\
  \hline
  売上高 & \makecell[r]{+8.2\\(過去最高)} \\
  \hline
\end{tabular}

这里表头“Year-on-year (%)” 用 \thead{Year-on-year\\(\%)} 堆成两行,正文中的数值也用 \makecell[r]{+8.2\\(record high)} 设为右对齐两行。二者都只是 在一个单元格内部 换行,并没有与相邻单元格合并。若内容很长,希望按宽度自动换行,正确做法是使用 p{width}(或其同类),而不是 \makecell

对齐陷阱与工具选择

常见绊脚点可以这样概括。第一是 垂直居中\multirow 文本默认位于行的中央,但根据行高和线条粗细,可能看起来略高或略低;这时可通过 [vpos] 选择 t / b,或给 [vmove] 一个小长度微调。第二是 行一致性:即使某行含有 \multicolumn& 的数量加上合并跨距也必须等于声明的列数。第三是 嵌套顺序:块合并时必须把 \multirow 放在 \multicolumn 内部。

工具选择很简单:横向跨列用 \multicolumn,纵向跨行用 \multirow,矩形块两者并用,只想在一个单元格内换行才用 \makecell。如果要让长文本 按宽度 自动换行,正确做法是使用 p{width}(需要垂直居中则用 arraym{width}),而不是这些命令。列指定本身见“列指定、对齐与宽度”,超出版面的宽表见“高级表格环境”。