セル結合

LaTeX の表には、本当の意味での「セル結合」がありません。横方向の \multicolumn は、latex.ltx を読むと \multispan すなわち TeX の原始命令 \omit から始まっています——\omit は「このセルの列テンプレートを 捨てる」という命令で、隣とくっつけているのではなく、決められた型を無視して自前で幅を取っているだけです。縦方向の \multirow はもっと大胆で、下の行に食い込む大きな箱に文字を置いているだけ。この二つの実装が、! Misplaced \omit. というエラーから、下の行に文字が重なる事故まで、このページで扱うつまずきのほとんどを説明してくれます。あわせて、結合したセルの下に罫線を引くときの厄介ごと(\cline\cmidrule)も見ていきます。

横方向の結合——\multicolumn と、行の先頭でしか使えない理由

書式は三引数の \multicolumn{n}{spec}{text}n はまたぐ列の本数、specできあがった一つのセル の列指定、text が中身です。標準の LaTeX に組み込まれているのでパッケージは要りません。肝心なのは、spec結合後の 1 列ぶん の指定であって、元の n 列の指定を引き継がないこと——だから lcr のいずれか一つを必ず書きます。二つ書いた \multicolumn{2}{cc}{…}! Missing \endgroup inserted.! Extra alignment tab has been changed to \cr. を続けて出して壊れます。逆に spec には縦罫 |@{…} も書けるので、この結合セルについてだけ 罫線や列間の空きを上書きできます。

\multicolumnセルのいちばん先頭に置かなければなりませんX \multicolumn{1}{c}{Y} & Z のように何かを書いた後で呼ぶと ! Misplaced \omit. になります。冒頭で触れたとおり、\multicolumn の実体は \omit で、これは「このセルの型を使わない」と宣言する原始命令だからです。宣言はセルが始まる前にしか意味を持ちません。エラーメッセージが \multicolumn ではなく \omit の名で来るのは、そういう事情です。

latex
\begin{tabular}{lcc}
  \hline
  \multicolumn{3}{c}{Sales summary} \\
  \hline
  Item & H1 & H2 \\
  \hline
  Domestic & 120 & 145 \\
  Overseas & 80  & 96  \\
  \hline
\end{tabular}

1 行目は、本来 3 列に分かれるはずの行を \multicolumn{3}{c}{Sales summary} で一つの中央揃えセルにまとめ、表全体の見出しにしています。結合した行でも、その行のセルの合計は 必ず宣言した列数に一致 させる必要がありますが、ここでは \multicolumn{3}{…} が 3 列ぶんを引き受けるので & は要りません。もう一つ覚えておきたいのが n1 にする 使い方です。列はまたがないまま、そのセルだけ揃えを上書きする ことも、その位置の縦罫 | を消す こともできます。数値列(r)の見出しだけ中央に置きたいなら \multicolumn{1}{c}{Header}、外枠付きの表で 1 マスだけ縦罫を抜きたいなら spec| を書かなければよいわけです。

外枠付きの表で二つの \multicolumn を横に並べるときは、縦罫を書くのはどちらか一方だけ にしてください。\multicolumn{2}{|c|}{左} のあとに \multicolumn{2}{|c|}{右} と続けると、境目に 罫線が二本重なって描かれ、その一本だけが太く見えます。\arrayrulewidth を大きくすると一目瞭然です。正しくは、後続を \multicolumn{2}{c|}{右} として先頭の | を落とします。これは \multicolumn が「捨てた型の代わりに、書いたものだけを描く」という素直な実装ゆえの副作用で、重複の面倒までは見てくれません。

縦方向の結合——multirow パッケージと \multirow の引数

縦にまたぐセルは標準命令では作れず、multirow パッケージ を読み込みます(TeX Live 2024 同梱は 2021 年 3 月 15 日版 v2.8)。書き忘れると単に ! Undefined control sequence. です。完全な書式は \multirow[vpos]{nrows}[bigstruts]{width}[vmove]{text} の六つで、必須は nrowswidthtext の三つだけ。nrows はまたぐ行数、width はセルの幅、text が中身です。幅に * を渡せば中身の自然な幅で組まれ、\multirow{3}{*}{Label} がいちばん素直な形になります。

決定的に大切なのは、またがれる下の行のセルを空にしておく ことです。\multirow は上の行に置き、続く行では同じ列の位置を & だけで送ります。公式ドキュメントの言い方では「他の行のその列は空にしておくこと。さもないと \multirow が作ったものがそれを上書きする」。実際に中身を書いてしまうと、エラーは出ないまま二つの文字が同じ場所に重なって刷られます。なお nrows負の値も取れます。正なら「この行と下の n−1 行」、負なら「この行と上の |n|−1 行」で、またぐ行数は同じ——命令を上端に書くか下端に書くかの違い だけです。小数も使えるので、\multirow{2.5}{*}{…} のように半端な値で高さを微調整することもできます。

document.tex
\usepackage{multirow}
% ...
\begin{tabular}{|l|l|c|}
  \hline
  \multirow{2}{*}{Fruit}     & Apple  & 380 \\
                             & Orange & 120 \\
  \hline
  \multirow{2}{*}{Vegetable} & Carrot & 90  \\
                             & Radish & 150 \\
  \hline
\end{tabular}
引数役割備考
[vpos]縦の揃え(任意・先頭)既定は c、ほかに t / b
nrowsまたぐ行数(必須)正で下方向、負で上方向。小数も可
[bigstruts]bigstrut の総数(任意)既定 0。t / b / tb を前置して片側だけ指定も可
widthセルの幅(必須)* は自然幅、= は列の幅、絶対値は parbox
[vmove]位置の微調整(任意・text の前)正で上へ、負で下へずらす
\multirowsetuptext の直前に展開される設定初期値は \raggedright。renewcommand で変更する

width* ではなく絶対値(\multirow{2}{4em}{…})を渡すと、中身はその幅の parbox として組まれ、長いラベルが折り返します。この形にしたとき、\multirow の文字が 両端揃えにならず左寄せに見える ことに気づくかもしれません。バグではなく仕様で、text の直前に展開されるフック \multirowsetup の初期値が \raggedright だからです。中央にそろえたいなら \renewcommand{\multirowsetup}{\centering} と書き換えます。もう一つ、width には = も渡せて、これは「いま入っている列に定義された幅を使う」という意味です——p{} 列や tabularxX 列の中で便利ですが、幅の定まっていない列で使うと妙に広い列ができあがります。

\multirow が場所を空けてくれない——文字が下の行にはみ出すとき

\multirow のいちばん有名な事故がこれです。\multirow は自分が必要とする縦のスペースを表に確保させません。 箱の高さは nrowsbigstruts から 推定 されるだけで、実際の行の高さを知らないからです。だから中身が背の高い箱になると、下の行や表の外へ そのままはみ出します。公式ドキュメントも薬の副作用一覧を例に、二つの \multirow が「高すぎて、一つめは二つめの項目に食い込み、二つめは表の外にはみ出す」と率直に書いています。中身の分量に対して nrows が小さすぎるとき、この症状が出ます。

直しかたは三つあり、公式ドキュメントが挙げるのは前の二つです。第一に、空の行を足して覆う ——足りないぶんだけ & & \\ を書き加えます。いちばん確実で、行数さえ数えればよい方法です。第二に、行そのものを縦に伸ばす ——幅ゼロの支柱、たとえば \newcommand{\mystrut}{\rule[-8pt]{0pt}{20pt}} を各行に置いて高さを稼ぎます(bigstrut パッケージの \bigstrut を使い、その回数を [bigstruts] に申告する手もあります)。第三に、nrows を実際より大きめに、あるいは小数で申告する ——手軽なぶん、罫線との関係が崩れやすいので最後の手段です。

document.tex
\usepackage{multirow}
% ...
% the label wraps to four lines but the block has only two rows,
% so raise nrows to 4 and add two empty rows to cover the overlap
\begin{tabular}{|l|c|}
  \hline
  \multirow{4}{4em}{A long label that wraps} & one \\
                                             & two \\
                                             &     \\
                                             &     \\
  \hline
  next & row \\
  \hline
\end{tabular}

同じ「行の高さを知らない」という弱点は、表のどこかに背の高い行があるとき にも顔を出します。公式ドキュメントの例は、3 行めだけが p{4cm} 列で長く折り返す表で、\multirow{3}*{Week 38} が本来の見た目の中心より上にずれてしまうというもの。行の高さがそろっていないと、\multirow の推定した中心と、目で見た中心が食い違うわけです。この種のずれは [vmove] に小さな長さを与えて手で直します。.1ex のような相対的な単位を使っておくと、後から本文の級数を変えても補正がだいたい生き残ります——これも公式ドキュメントの助言です。

結合セルに罫線が当たるとき——\hline ではなく \cline と \cmidrule

ここがこの話題でいちばん厄介なところです。\multirow でまたいだ行のあいだに \hline を書くと、罫線は 結合セルの文字を横切って引かれます ——ラベルが取り消し線を引かれたように見えるのは、\hline が行と行のあいだに表の幅いっぱいの \hrule を渡すだけで、上に何が乗っているかを知らないからです。\arrayrulewidth を太くすれば、文字が線に貫かれているのがはっきり見えます。対策は単純で、その列だけ罫線から外す こと——標準なら \cline{2-3}booktabs を使うなら \cmidrule{2-3} のように列の範囲を指定します。

document.tex
\usepackage{multirow}
% ...
% \hline here would draw straight through the word "Group";
% \cline{2-3} spares column 1
\begin{tabular}{|l|l|c|}
  \hline
  \multirow{2}{*}{Group} & alpha & 1 \\
  \cline{2-3}
                         & beta  & 2 \\
  \hline
\end{tabular}

\cline\cmidrule は範囲を指定できる点では同じですが、性格が違います\cline{i-j} は太さが \arrayrulewidth(既定 0.4pt)で、指定した列の端から端まできっちり伸びるので、隣り合う \cline が横につながって一本に見えます。booktabs\cmidrule{i-j} は太さが \cmidrulewidth(既定 0.03em、本文 10pt なら約 0.3pt)と細く、上下に \aboverulesep\belowrulesep の空きを取ります。さらに丸括弧の任意引数で端を詰められるのが実務上の要で、\cmidrule(lr){2-3} と書けば左右が少し短くなり、隣の \cmidrule との あいだに隙間ができて別々の罫線に見えます ——複数の見出しグループを並べるときの定番です。

latex
\usepackage{booktabs}
% ...
% two \multicolumn headers, each underlined by its own trimmed rule
\begin{tabular}{lcccc}
  \toprule
       & \multicolumn{2}{c}{2024} & \multicolumn{2}{c}{2025} \\
  \cmidrule(lr){2-3} \cmidrule(lr){4-5}
  Item & Q1 & Q2 & Q1 & Q2 \\
  \midrule
  Apple & 1 & 2 & 3 & 4 \\
  \bottomrule
\end{tabular}

これが \multicolumn と罫線を組み合わせた実務の定番形です。\multicolumn{2}{c}{2024} が二列ぶんの見出しを作り、その真下の \cmidrule(lr){2-3} が「この二列はひとまとまり」と示します。(lr) を省くと二本の罫線がつながって、グループの境目が見えなくなります。なお二本の \cmidrule同じ列範囲に重ねて 引きたいときは booktabs\morecmidrules を挟みます——普通に二つ続けて書くと同じ高さに並べようとするからです。色付きの表では \cline が背景色に塗りつぶされて見えなくなることがありますが、その症状と hhline を使う回避策は「表に色を付ける」のページで扱っています。

ブロック結合——\multirow は \multicolumn の内側に

縦横どちらにもまたぐ 長方形のブロック は、\multirow\multicolumn の組み合わせで作ります。順序は決まっていて、\multirow\multicolumn の内側に置く のが正解です。公式ドキュメントも \multicolumn{2}{c}{\multirow{3}{*}{Multi-multi}} を例に挙げ、逆の入れ子は「will not work」と明記しています。外側の \multicolumn が横方向を、内側の \multirow が縦方向を受け持つと覚えてください。そして \multirow の掟はここでも生きています——下の行の同じ位置は、\multicolumn の形を保ったまま 中身だけ空 にします。

document.tex
\usepackage{multirow}
% ...
\begin{tabular}{|l|l|c|}
  \hline
  \multicolumn{2}{|c|}{\multirow{2}{*}{Region and class}} & Count \\
  \multicolumn{2}{|c|}{}                                  &       \\
  \hline
  East & Kanto  & 12 \\
  \cline{1-3}
  West & Kansai & 9  \\
  \hline
\end{tabular}

1 マスで改行するだけなら結合ではない——makecell

ここで一つ区別しておきましょう。「1 マスの中で行を折り返したい」のは、セル結合ではありませんlcr の列は折り返さないので、セルの中に \\ を直接書きたくなりますが、それをやると エラーにならないまま表が静かに崩れます ——A & B\\C \\ と書くと、TeX は \\ を行末と読み、C は次の行の 1 列目として組まれます。エラーが出ないぶん、こちらのほうが厄介です。短い文字列を意図した位置で改行したいだけなら makecell パッケージ\makecell{…} がいちばん手軽です。

\makecell{line1\\line2} は、中身を 一列の小さな tabular として組み、\\ を強制改行として使えるようにします。任意引数で揃えも指定でき、\makecell[l]{…}(左寄せ)、\makecell[t]{…}(上端)のように 縦・横の揃えを一文字ずつ 渡します(既定は縦横とも中央)。見出し用には共通の書体と余白が設定された \thead{…} も用意されています。中身が長く、幅にあわせて 自動で 折り返してほしい場合は \makecell ではなく p{幅} 列(縦中央なら arraym{幅})を使うのが本筋です。

document.tex
\usepackage{makecell}
% ...
\begin{tabular}{lc}
  \hline
  \thead{Item} & \thead{Year on year\\(\%)} \\
  \hline
  Revenue & \makecell[r]{+8.2\\(record high)} \\
  \hline
\end{tabular}

どの道具をいつ使うか

選び分けは単純です。横にまたぐなら \multicolumn、縦にまたぐなら \multirow、長方形なら両者の併用(\multirow を内側に)、1 マス内で改行したいだけなら \makecell。長い文章を幅にあわせて折り返したいなら、そもそもどれでもなく p{幅} 列の仕事です。そして結合を含む表を書き終えたら、必ず PDF を見て三点を確かめてください——下の行のセルを空にし忘れていないか(文字が重なっていないか)、\multirow の箱が下にはみ出していないかnrows を足すか空行を入れる)、そして 罫線が結合セルを横切っていないか\hline\cline\cmidrule に替える)。この三つで、実際に起きる事故のほとんどが片付きます。