LaTeX 表格怎么做:三线表、列宽与合并单元格

LaTeX 表格从入门到论文常用写法:tabular 的列格式与横竖线,booktabs 三线表,p 列和 tabularx 控制列宽与自动换行,multirow 和 multicolumn 合并单元格,表格标题、引用和跨页长表格,每个示例都能直接打开编译。

最后核对:2026-10-24

LaTeX 的表格由两层组成:tabular 环境负责排出表格本身,table 浮动体负责标题、编号和在页面上的位置。先分清这两层,后面的问题(标题怎么加、表格为什么跑到下一页、为什么引用编号不对)就都好理解了。

最基本的表格怎么写

% !TEX program = xelatex
% title: LaTeX 表格入门
\documentclass{ctexart}

\begin{document}

\section{最简单的表格}
% tabular 的参数是列格式:l 左对齐,c 居中,r 右对齐,| 竖线
% 单元格之间用 & 分隔,每行用 \\ 结束,\hline 画横线
\begin{tabular}{|l|c|r|}
  \hline
  姓名 & 性别 & 成绩 \\
  \hline
  张三 & 男 & 92 \\
  李四 & 女 & 88 \\
  \hline
\end{tabular}

\section{带标题、可引用的表格}
% table 是浮动体:负责标题、编号和位置;tabular 负责表格本身
如表~\ref{tab:score} 所示,两位同学的成绩都在 85 分以上。

\begin{table}[htbp]
  \centering
  % 表格的标题习惯放在表格上方
  \caption{期末成绩}
  % \label 必须写在 \caption 之后,否则 \ref 得到的是节号
  \label{tab:score}
  \begin{tabular}{lcc}
    \hline
    姓名 & 数学 & 英语 \\
    \hline
    张三 & 92 & 85 \\
    李四 & 88 & 90 \\
    \hline
  \end{tabular}
\end{table}

\end{document}
LaTeX 表格入门在 JointTex 中打开

tabular 的参数是列格式,每个字母代表一列:

  • l、c、r:左对齐、居中、右对齐,列宽由内容决定;
  • |:在两列之间画竖线;
  • p{3cm}:固定宽度的列,内容超长时自动换行(见下文)。

表格内容里,& 分隔单元格,\\ 结束一行,\hline 画一条贯穿整行的横线。每行的 & 个数必须等于列数减一,多了会报 Extra alignment tab has been changed to \cr。

表格标题和引用怎么加

把 tabular 放进 table 环境,用 \caption 写标题,用 \label 打标签,正文里用 \ref 引用:

  • 中文论文的习惯是表题在表格上方,所以 \caption 写在 tabular 前面;图题则在图的下方。
  • \label 一定要写在 \caption 之后。写在前面时,\ref 拿到的是当前节号而不是表号,这是"表格引用编号不对"最常见的原因。
  • \centering 让表格居中。不要用 center 环境代替,它会在上下多加一段空白。
  • 用 ctex 文档类时,标题前缀自动是"表";用英文文档类时是"Table"。

table 的可选参数 [htbp] 控制位置,表格"乱跑"的原因和解决办法与图片相同,见插图与浮动体。

论文里的三线表怎么做

学术论文最常见的是三线表:顶线、底线较粗,表头下面一条细线,没有竖线。booktabs 宏包提供了这三条线:\toprule、\midrule、\bottomrule,以及只画在部分列下面的 \cmidrule。

% !TEX program = xelatex
% title: 三线表(booktabs)
\documentclass{ctexart}
\usepackage{booktabs} % 提供 \toprule、\midrule、\bottomrule、\cmidrule

\begin{document}

表~\ref{tab:result} 是论文里常见的三线表:
顶线和底线粗,栏目线细,没有竖线。

\begin{table}[htbp]
  \centering
  \caption{不同方法的实验结果}
  \label{tab:result}
  \begin{tabular}{lccc}
    \toprule
    方法 & 准确率(\%) & 召回率(\%) & 耗时(s) \\
    \midrule
    方法 A & 91.2 & 88.5 & 12.3 \\
    方法 B & 93.6 & 90.1 & 15.8 \\
    本文方法 & \textbf{95.4} & \textbf{92.7} & 13.1 \\
    \bottomrule
  \end{tabular}
\end{table}

% \cmidrule{2-3} 只在第 2~3 列下面画细线,(lr) 让线两端缩进一点
\begin{table}[htbp]
  \centering
  \caption{分组表头}
  \label{tab:group}
  \begin{tabular}{lcccc}
    \toprule
         & \multicolumn{2}{c}{训练集} & \multicolumn{2}{c}{测试集} \\
    \cmidrule(lr){2-3} \cmidrule(lr){4-5}
    模型 & 准确率 & 损失 & 准确率 & 损失 \\
    \midrule
    基线 & 0.92 & 0.21 & 0.88 & 0.30 \\
    改进 & 0.95 & 0.15 & 0.91 & 0.24 \\
    \bottomrule
  \end{tabular}
\end{table}

% 注意:三线表不要再加竖线 |,booktabs 的横线与竖线接不上

\end{document}
三线表(booktabs)在 JointTex 中打开

几个要点:

  • \cmidrule(lr){2-3} 在第 2 到第 3 列下面画线,(lr) 让线的左右两端缩进一点,相邻两组表头的线就不会连在一起。
  • booktabs 的文档明确建议不要用竖线,也不要用双横线。它的横线上下带有额外的间距,文档也说明这些横线不保证能和竖线接上,混用时常见断开的缺口。
  • 单位、百分号写在表头里,如"准确率(%)"。在 LaTeX 源码里 % 是注释符,要写成 \%。

列太宽、文字超出页面怎么办

l、c、r 列不会换行,内容一长,表格就会伸出页边,日志里出现 Overfull \hbox。解决办法是给列一个宽度:

  • p{5cm}:列宽固定为 5cm,文字在列内自动换行。array 宏包还提供 m{5cm}(垂直居中)和 b{5cm}(底端对齐)。
  • tabularx 环境:先指定整个表格的宽度(常用 \linewidth),再把需要自动换行的列写成 X,这些列平分剩余宽度。表格因此正好占满一行,不会超出。
  • X 列和 p 列一样两端对齐;列很窄、英文较多时,可以定义 >{\raggedright\arraybackslash}X 让它左对齐。想要居中的 X 列,用 array 宏包的 >{...} 在列前插入命令,定义一个新列型:\newcolumntype{Y}{>{\centering\arraybackslash}X}。\arraybackslash 必不可少,否则这一列里的 \\ 会失效。
% !TEX program = xelatex
% title: 表格列宽与自动换行
\documentclass{ctexart}
\usepackage{booktabs}
\usepackage{array}    % 提供 >{...} 列前命令和 m{}、b{} 列
\usepackage{tabularx} % 提供按总宽度自动分配的 X 列

% 定义一个居中的 X 列:Y
\newcolumntype{Y}{>{\centering\arraybackslash}X}

\begin{document}

\section{固定列宽:p\{宽度\}}
% p{5cm} 列宽固定为 5cm,内容超长时自动换行
% 另有 m{宽度}(垂直居中)和 b{宽度}(底端对齐),需要 array 宏包
\begin{tabular}{lp{5cm}l}
  \toprule
  术语 & 解释(p 列) & 备注 \\
  \midrule
  浮动体 & 可以在页面中移动位置的对象,如图和表,由 LaTeX 决定放在哪里。 & 见插图一节 \\
  \bottomrule
\end{tabular}

\section{占满整行:tabularx}
% 第一个参数是表格总宽度,X 列平分剩下的宽度
\begin{table}[htbp]
  \centering
  \caption{tabularx 示例}
  \begin{tabularx}{\linewidth}{lXY}
    \toprule
    编号 & 说明(X 列,两端对齐,自动换行) & 状态(Y 列,居中) \\
    \midrule
    1 & 表格的总宽度固定为行宽,长文字会在 X 列里自动换行,不会超出页面。 & 完成 \\
    2 & 短内容。 & 进行中 \\
    \bottomrule
  \end{tabularx}
\end{table}

\section{整体缩小}
% 表格太宽时,优先改列宽或换行;字号可以小一号,但不要用 \resizebox 硬缩
{\small
\begin{tabular}{lcccccc}
  \toprule
  数据集 & A & B & C & D & E & F \\
  \midrule
  结果 & 1.0 & 2.0 & 3.0 & 4.0 & 5.0 & 6.0 \\
  \bottomrule
\end{tabular}}

\end{document}
表格列宽与自动换行在 JointTex 中打开

表格只是略宽时,可以把字号调小一号(如 \small)。不建议用 \resizebox 把整个表格硬缩到行宽:缩放后表格的字号和正文不一致,线宽也跟着变细。

怎么合并单元格

  • 跨列用 LaTeX 自带的 \multicolumn{列数}{对齐}{内容},例如 \multicolumn{2}{c}{成绩}。它也常用来单独改变某个单元格的对齐方式。
  • 跨行用 multirow 宏包的 \multirow{行数}{宽度}{内容},宽度写 * 表示按内容的自然宽度。被占用的下面几行,对应的单元格要留空(但 & 不能少)。
  • 画了竖线的表格里,\multicolumn 的对齐参数要把竖线一起写上,如 {|c|},否则这一格的竖线会消失。
  • 不用 booktabs 时,只在部分列下面画横线用 \cline{2-3};用 booktabs 时用 \cmidrule{2-3}。
% !TEX program = xelatex
% title: 合并单元格
\documentclass{ctexart}
\usepackage{booktabs}
\usepackage{multirow} % 提供 \multirow(跨行)

\begin{document}

% \multicolumn{列数}{对齐}{内容}:跨列,LaTeX 自带
% \multirow{行数}{宽度}{内容}:跨行,宽度写 * 表示按内容自然宽度
如表~\ref{tab:merge} 所示,“文科”“理科”各占两行,
“成绩”横跨两列。

\begin{table}[htbp]
  \centering
  \caption{合并单元格示例}
  \label{tab:merge}
  \begin{tabular}{llcc}
    \toprule
    \multirow{2}{*}{类别} & \multirow{2}{*}{科目} & \multicolumn{2}{c}{成绩} \\
    \cmidrule(lr){3-4}
         &      & 期中 & 期末 \\
    \midrule
    % 被 \multirow 占用的下一行,对应单元格留空
    \multirow{2}{*}{文科} & 语文 & 85 & 88 \\
                          & 历史 & 90 & 92 \\
    \midrule
    \multirow{2}{*}{理科} & 数学 & 95 & 93 \\
                          & 物理 & 87 & 91 \\
    \bottomrule
  \end{tabular}
\end{table}

% 带竖线的表格里,\multicolumn 的对齐参数要自己写上竖线,如 {|c|};
% 只在部分列画横线用 \cline{3-4}(不用 booktabs 时)
\begin{tabular}{|c|c|c|}
  \hline
  \multicolumn{3}{|c|}{横跨三列的标题} \\
  \hline
  \multirow{2}{*}{跨两行} & a & b \\
  \cline{2-3}
                          & c & d \\
  \hline
\end{tabular}

\end{document}
合并单元格在 JointTex 中打开

表格太长、要跨页怎么办

table 是一个整体,不能跨页。表格超过一页时,用 longtable 宏包的 longtable 环境代替 table 加 tabular。它可以分别设置首页表头、续页表头和每页底部:

\usepackage{longtable}
\usepackage{booktabs}

\begin{longtable}{lcr}
  \caption{长表格示例}\label{tab:long} \\
  \toprule
  编号 & 名称 & 数值 \\
  \midrule
  \endfirsthead          % 以上内容只出现在第一页
  \multicolumn{3}{l}{(续表~\ref{tab:long})} \\
  \toprule
  编号 & 名称 & 数值 \\
  \midrule
  \endhead               % 以上内容出现在后续每一页的顶部
  \bottomrule
  \endfoot               % 每一页的底部
  1 & 甲 & 10 \\
  2 & 乙 & 20 \\
  % ……更多行
\end{longtable}

注意:longtable 不放在 table 环境里,它的 \caption 写在环境内部、以 \\ 结尾;它需要多编译一次才能算准各页的列宽。

表格行距太挤怎么调

表格的行高由 \arraystretch 控制,默认是 1。整体调大可以在表格前写:

\renewcommand{\arraystretch}{1.3}

把这行放在 table 环境里面,只影响这一个表格;放在导言区,影响全文所有表格。三线表的 \toprule、\midrule 本身已经在线的上下留了空隙,通常不需要再调。

数字怎么按小数点对齐

实验数据表里,小数位数不同的数字居中后参差不齐。siunitx 宏包的 S 列按小数点对齐,table-format=3.2 表示整数部分最多 3 位、小数部分 2 位:

\usepackage{siunitx}

\begin{tabular}{l S[table-format=3.2]}
  \toprule
  样本 & {均值} \\
  \midrule
  甲 & 1.5 \\
  乙 & 123.25 \\
  \bottomrule
\end{tabular}

S 列里不是数字的内容(比如表头)按 siunitx 文档的建议用花括号包起来,如 {均值},宏包就会把它当作文字处理,而不会尝试把其中像数字的部分拿去对齐。

表格下方的注释怎么写

表格下方的"注:""a. 数据来源……"这类注释,可以用 threeparttable 宏包:表格放进 threeparttable 环境,单元格里用 \tnote{a} 标注,表格后面用 tablenotes 环境写注释内容,每条以 \item[a] 开头。它让标题和注释的宽度与表格本身一致,所以表格很窄时,标题也会跟着折行。

表题格式怎么改成"表 1 标题"

ctex 文档类默认的表题是"表 1: 标题"。很多学校要求编号和标题之间用空格而不是冒号,或者表题用小一号的字。用 caption 宏包统一设置,图题和表题都会生效:

\usepackage{caption}
\captionsetup{labelsep=quad, font=small}

labelsep=quad 表示编号后空一个 quad 的距离,也可以用 space(一个空格)或 period(句点)。只改表题时写 \captionsetup[table]{...}。

有没有更快的办法

手写大表格容易错位。可以先在 Excel 里排好,再用 Excel2LaTeX 这类插件或在线表格生成器导出 tabular 代码,然后按本文的方法换成三线表、调整列宽。生成的代码一定要再检查一遍 & 的数量和特殊字符的转义。

本文的示例都可以在 JointTex 中一键打开为新项目并直接编译,可以在示例的基础上改成自己的表格。表格里出现中文时要用 XeLaTeX 编译,见中文排版与字体;编译报错可以对照常见编译报错解读。

JointTex

Browser compatibility

JointTex could not start

The application did not finish loading. Check your connection, then try again.

Supported versions

  • Chrome and Edge 88 or later
  • Firefox 84 or later
  • Safari and iOS Safari 14 or later
Reload