ページをまたぐ表(longtable)

table 環境に入れた表は、何行あろうと 改ページしません。しかも、あふれてもエラーは出ません——手元の TeX Live 2024 で 119 行の表を table で包むと、出力は 3 ページではなく 1 ページになり、残りの行は紙の下へ静かに消えました。この壁を壊し、表を複数ページに分割してくれるのが LaTeX の longtable パッケージです。ただし longtable の本当の仕事は「改ページすること」ではありません。すべてのページで列幅をそろえること——そのために .aux ファイルへ実測値を書き出し、Table widths have changed. Rerun LaTeX. という警告であなたに二回目のコンパイルを要求します。このページでは、その二回のコンパイルが何を買っているのかを、supertabular との実測比較で確かめながら見ていきます。

table 環境の表が改ページしない理由

tablefigure と同じ フロート(浮動体) で、LaTeX はフロートを「一ページに収まる分割不能な一個の箱」として扱うからです。箱の中身は箱ごとページの上や下へ運ばれます。運べる以上、途中で切ることはできません。だから中の tabular がどれだけ縦に伸びても分割されず、収まらなければ紙からはみ出します。厄介なのは、それが警告にならないこと。同じ 119 行のデータで実験すると、table で包んだ場合の出力は 1 ページ、包まなかった場合は 3 ページでした。エラーメッセージは一行も出ません。PDF を最後まで見ないと気づけない種類の事故です。

つまり「ページをまたぐ表」はフロートという枠組みそのものと相容れません。必要なのは、表を 本文と同じ流れに置き、段落と同じように TeX の改ページアルゴリズムに任せる 仕組みです。それが longtable です。作者は arraytabularxdcolumn などを書いた David Carlisle、LaTeX に標準で付いてくる tools バンドルの一員なので、追加インストールは要りません。

longtable の書き方 — tabular と何が違うか

書き方はほとんど tabular と同じです。\usepackage{longtable} を読み込み、\begin{longtable}{l l r} のように 列指定を必須引数 に取り、& で列を区切り \\ で行を閉じる。lcrp{幅}\hline\multicolumn もそのまま通ります。違うのは三点だけです。第一に、table 環境で包んではいけません——包むとフロートに戻ってしまい、冒頭の 1 ページ問題が再発します。第二に、列指定の に配置用の任意引数 [c][r][l] を書けます。第三に、longtable は自分でキャプションを持ちます(後述)。改ページは行と行のあいだ、または \hline の位置でだけ起こり、p 列の一セルの途中では起こりません。

位置と前後の空きは、\begin{document} の後で自由に変えられる長さで決まります。既定値は TeX Live 2024 で次のとおりでした——\LTleft\LTright はどちらも 0pt plus 1fill、つまり 左右から同じ量だけ押されて中央に来ます。左寄せにしたければ \setlength{\LTright}{0pt plus 1fill} を残して \setlength{\LTleft}{0pt} にします。表の上下の空きは \LTpre\LTpost で、どちらも既定 12pt plus 4pt minus 4pt です。

見出しと脚を毎ページ繰り返す — endhead と endfoot

表の冒頭に 四つのマーカー を並べ、それぞれ「ここまでの行を、どのページに繰り返すか」を宣言します。マーカーは対応する行の末尾で \\代わりに 置きます。四つとも省略可能で、全ページ同じ見出しでよければ \endhead 一つで足ります。

マーカー直前の行が出る場所典型的な中身
\endfirsthead最初のページの表頭だけ\caption{…} と列見出し
\endhead最初以外のすべてのページの表頭「(つづき)」+列見出し
\endfoot次ページへ続くページの脚(最終ページ以外)「次ページに続く」の行
\endlastfoot最終ページの表の末尾だけ締めの罫線、注記
\killどこにも出ない(幅の測定だけに使われる)一番幅広くなるはずのダミー行
document.tex
\documentclass{article}
\usepackage{longtable}
\begin{document}

\begin{longtable}{l l r}
  % head of the first page only
  \caption{Annual sales log}\\
  \hline
  Date & Item & Amount \\
  \hline
  \endfirsthead

  % head of every later page
  \multicolumn{3}{l}{\small (continued)}\\
  \hline
  Date & Item & Amount \\
  \hline
  \endhead

  % foot of every page that continues
  \hline
  \multicolumn{3}{r}{\small Continued on next page}\\
  \endfoot

  % foot of the last page
  \hline
  \endlastfoot

  % everything below the markers is real data
  2026-01-05 & Apple  & 380 \\
  2026-01-06 & Orange & 120 \\
  % ...rows continue; pages are broken automatically...
\end{longtable}

\end{document}

順番が肝心です。四つのマーカーは 必ずこの順で、表の一番上に 並べます。そして マーカー群より下に書いた行が本物のデータとして各ページへ流し込まれます。逆に言えば、\endlastfoot の後に書いた最初の行から表の中身が始まる、ということ。この順序を崩すと、見出しのつもりの行がデータの一行目として本文に出てしまいます。\kill は少し毛色が違い、測定だけして印字しない行 を作ります。「見出しは短いが、100 ページ目に一度だけ長い値が来る」ようなときに、先頭で \kill 行に最大幅の見本を書いておくと、最初から広い列で組めます。

Table widths have changed. Rerun LaTeX. — なぜ二回コンパイルするのか

各ページの列幅をそろえるためです。 longtable は表をページに分けて組みますが、あるページの一番幅広いセルが分かるのは、そのページを組み終わったあと。ページごとに独立して組めば、ページごとに違う列幅になってしまいます。そこで longtable は測った幅を .aux ファイルに書き出し、次の実行でそれを読み戻して全ページ共通の幅として使います。だから初回のコンパイルでは、こういう警告が出ます。

log
Package longtable Warning: Column widths have changed
(longtable)                in table 1 on input line 24.


Package longtable Warning: Table widths have changed. Rerun LaTeX.

警告を無視するとどうなるか、実測してみましょう。3 ページに分かれる表の右端の列見出し「Amount」の位置を PDF から拾うと、初回は x = 320.41pt、データ本体は x = 488.69pt ——見出しと数値が別々の場所に立っています。二回目を走らせると見出しは x = 471.53pt に移り、全ページで同じ位置にそろいました。つまり初回の出力は「列が細すぎて見出しだけ左にずれた表」であり、これが「一度コンパイルしたら表が変」の正体です。

その .aux ファイルは覗けます。三列の longtable を組んだ直後の中身がこれです。\LT@i は「この文書で一つ目の longtable」の意味で、二つ目は \LT@ii になります。第二引数が列ごとの実測幅で、次の実行はこの数字をそのまま使います。

document.aux
\gdef \LT@i {\LT@entry
    {2}{58.6668pt}\LT@entry
    {2}{274.36153pt}\LT@entry
    {1}{47.55566pt}}

測定は一気にではなく かたまり単位 で行われ、その大きさを決めるのがカウンタ LTchunksize(既定 200 行)です。行数の多い表で TeX のメモリを使い切ってしまうときは、\setcounter{LTchunksize}{10} のように小さくします。逆に大きくすると .aux の往復が減って収束が速くなることがあります。実務上は、latexmk を使えばこの往復を気にする必要はありません——警告が消えるまで自動で回してくれます。

キャプションと番号 — LTcapwidth の既定は 4 インチ

longtable はフロートではないのに、自前の \caption{…} を持ちます。番号は標準と同じ table カウンタで進むので「表 N」として自動採番され、\listoftables にも載ります。キャプションは表レイアウトの一部なので、\caption{…}\\ のように 見出しブロック(\endfirsthead の前)に置き、\\ で行を閉じる のが約束です。ここで一つ意外なのが幅で、キャプション幅 \LTcapwidth の既定は 4 インチ= 289.08ptarticle\textwidth は 345pt ですから、既定のままだと キャプションだけ本文より 56pt 狭い ことになります。本文幅にそろえたければ \setlength{\LTcapwidth}{\textwidth} と書きます。

残りは細かな約束ごとです。番号を付けたくない ときは \caption*{…}(番号も図表一覧の項目も付きません)。二ページ目以降の「(つづき)」のような 従属キャプション は、図表一覧に二重に載らないよう 任意引数を空にした \caption[]{…} で書きます。そして相互参照の \label{…}繰り返される \endhead の中に置いてはいけません——ページの数だけ同じラベルが定義されてしまいます。\endfirsthead の中か、表の本文の一行目に置いてください。

booktabs の罫線は改ページでどうなるか

\toprule\midrule\bottomrulelongtable の中でそのまま使えます。booktabs は 2000 年の版で longtable 対応を入れており、booktabs.sty の中に \ifx\longtable\undefined という分岐が残っています。ただし挙動には一つ非対称があります——longtable は改ページのために \hline を自動で二重にする(切れ目の上下に一本ずつ引くため)のに対し、booktabs の罫線は二重になりません。だから、罫線がちょうど改ページ位置に落ちてしまった場合は、booktabs の説明書も言うように 手で調整する(多くは、その罫線を消す)しかありません。実務的には \endfoot\endhead に罫線を持たせて、切れ目に罫線が来ないように設計するのが正解です。

おまけがあります。\cmidrule にしか使えないはずの 左右の切り詰め指定 が、longtable の中でだけ \toprule\midrule\bottomrule にも効きます。\toprule(r) と書けば右端が半角分内側に、\midrule(lr) なら左右とも内側に入ります。TeX Live 2024 で longtablebooktabs を一緒に読み込んで実際に通りました。逆に言えば、tabular の中で同じことは書けません——booktabs の作者は説明書のなかで、どうしても切り詰めた罫線が欲しければ表を全部 longtable にしてしまえ、と半ば冗談で書いています。

supertabular と xtab — 一回で済む代わりに列がずれる

ページをまたぐ表を作るパッケージは longtable だけではありません。supertabular(Johannes Braams・Theo Jurriens)と、その派生の xtab(Peter Wilson)は、まったく別の作戦をとります。longtable が「表全体を組んで TeX の改ページに任せる」のに対し、こちらは 「ページの残りの高さを測り、そこに入るだけの tabular を新しく作って置く」 ——つまりページごとに独立した tabular を並べているのです。だから .aux の往復が要らず、一回のコンパイルで完成します

ただし、その代償はそのまま見た目に出ます。同じ 119 行のデータで、90 行目にだけ極端に長い項目を混ぜて比べてみました。supertabular では列見出し「Amount」が 1・2 ページ目で x = 249.16pt、長い項目が来る 3 ページ目で x = 471.53pt ——ページをめくった瞬間、表の幅が変わります。同じデータの longtable は、二回目のコンパイル後に 三ページとも x = 471.53pt でした。二回コンパイルするというのは、この一貫性を買うということです。書式の書き方も違い、supertabular は見出しと脚を 環境の外側で \tablefirsthead\tablehead\tabletail\tablelasttail として宣言し、キャプションは \topcaption\bottomcaption を使います。xtab はこれに、切れ目が不格好にならないよう最低行数を指定する機能などを足したものです。

折り返す X 列も改ページさせたい — xltabular と ltxtable

longtable の列指定は tabular と同じなので、長文は p{幅} に固定幅で入れて折り返すことになります。「残り幅いっぱいに自動で広がる列」がほしければ tabularxX ですが、tabularx 環境そのものは改ページできません。この二つをつなぐ橋が二本あります。xltabular(Rolf Niepraschk・Herbert Voß)は「X 列を持つ longtable」で、\begin{xltabular}{\linewidth}{l X r} のように 総幅と列指定 を取り、\endfirsthead などのマーカーもそのまま使えます。内部で ltablex を読み込みますが、既存の tabularx 環境の動作は変えません。

document.tex
\documentclass{article}
\usepackage{xltabular}
\begin{document}

\begin{xltabular}{\linewidth}{l X r}
  \caption{Glossary}\\
  \hline
  Term & Description & Page \\
  \hline
  \endfirsthead
  \hline
  Term & Description & Page \\
  \hline
  \endhead

  longtable  & Breaks across pages; sits in the text flow, not in a float. & 12 \\
  xltabular  & A longtable whose X column takes the leftover width.       & 34 \\
\end{xltabular}

\end{document}

もう一本の橋が、同じ David Carlisle による ltxtable です。こちらは表の本体を 別ファイルに書き出し\LTXtable{\textwidth}{ファイル名} で読み込みます。中身は X 列を持つ longtable で、ltxtabletabularx の幅計算を一度走らせてから longtable に渡す、という段取り。ファイルを分ける手間はありますが、tabularx の反復展開と longtable.aux 往復が干渉しないので、長い表で安定します。使い分けは単純です——手軽さなら xltabular、大きく複雑な表で挙動が怪しいときは ltxtable。なお xltabular には、\caption を書かないかぎり table の番号を消費しないという細かな違いもあります。