> For the complete documentation index, see [llms.txt](https://ayakaleaf-pro.ayaka.space/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://ayakaleaf-pro.ayaka.space/latex/zh-cn/shen-du-wen-zhang/15-how-do-tex-engines-typeset-tables-2.md).

# TeX 引擎如何排版表格 2

## TeX 引擎如何排版表格 2

## TeX 引擎将表格称为对齐（alignments）

在 [TeX 源代码文档](https://www.overleaf.com/latex/examples/typeset-the-source-code-documentation-for-tex-e-tex-or-pdftex/qkgfgyspnhcv) Knuth 并没有讨论 TeX“排版表格”的能力，而是描述了 TeX 用来构造所谓 *对齐*。TeX 的表格排版实际上是一个自动的盒子对齐过程：排列各个盒子（表格单元格、行和列），以获得美观的矩形网格或阵列——当然，作为 TeX，这其中还有 *许多* 其中的细微差别。

“对齐”这一术语也体现在所有 TeX 引擎内置的两个表格排版命令名称中：

* `\halign` （水平对齐），以及
* `\valign` （垂直对齐）。

我们将在本系列文章中逐步探讨这两个命令，首先更正式地概述其格式/结构的 `\halign` 和 `\valign` 命令，为本系列后续的深入文章打下基础。

### TeX 的表格由盒子和间距构成

单个表格单元格通常包含各种内容，例如文本行、数学公式或图形，这会生成一组宽度、高度或深度各不相同的已排版材料单元格。TeX 必须设法处理这些内容尺寸各异的单元格，构造出最终表格，使每一行具有某个高度、每一列具有某个宽度。TeX 需要从这组可变大小的表格单元格中推导出各行高度和各列宽度的合适数值。

然而，TeX 在将内容排版之前无法知道每个单元格内容的真实尺寸；因此，TeX 会遍历整个表格，逐个排版每个单元格，以获取完成表格布局所需的尺寸数据。根据这些尺寸数据，TeX 能确定每一行的正确高度以及每一列的宽度。TeX 还可能遇到空单元格，或用户希望跨越多个列或多个行的单元格，所有这些都必须被 TeX 小心地纳入计算。经过对这组杂乱的单元格（盒子）尺寸数据进行“过滤”之后，TeX 才能确定一个中的列宽最终值 `\halign`，或中的行高 `\valign` ，并在其表格布局算法的最终阶段使用这些值。

实际上，在“幕后”，TeX 的表格排版由几个步骤组成。概括来说，TeX 首先会排版一个表格的“草稿”或“未完成”版本，同时捕获并处理单元格尺寸数据——以及任何 `\span` 在表格中使用的命令数据。在最后几个步骤中，TeX 会重新处理该“未完成”版本的表格，以最终确定 `\halign` 列宽或 `\valign` 行高并实现完整布局——这些我们将在本系列文章中探讨。

## \halign 和 \valign：构造表格的两种方式

所有 TeX 引擎都提供两种 *内置的* 用于排版表格（对齐）的命令（原语）： `\halign` 和 `\valign`，它们共享许多核心特性，但在一些根本方面也有所不同。它们之间的关键区别在于 `\halign` 和 `\valign` 它们构造各自表格的方式：按行还是按列：

* `\halign`：按行排版表格，创建逐行堆叠的各个行，从而生成表格的列
* `\valign`：按列排版表格，创建逐列堆叠的各个列，从而生成表格的行

### \halign

下图展示了由 `\halign`创建的表格结构。该表格按行排版，各个行垂直堆叠。其结果包括：

* 表格的列来自表格行的垂直堆叠
* 页面断行可以发生在表格行之间
* 非表格内容可以插入到行之间（通过 `\nolign`，我们稍后会讲到）

![](/files/ed946201b543af84247129d7f6cadd644105bc28)

### \valign

下图展示了由 `\valign`。该表格按列排版，各个列水平（并排）堆叠。其结果包括：

* 表格的行来自表格列的水平堆叠
* 换行可以发生在表格列之间
* 非表格内容可以插入到列之间（通过 `\noalign`，我们稍后会讲到）

![](/files/bdc23a6d1c193a9bb9abb345a9848de7fb123042)

### 示例

下面的示例旨在突出显示按行 *与*。\halign 和 \valign 的按列方式。

```latex
\documentclass{article}
\begin{document}
\pagestyle{empty}
% 紧贴的盒子边框
\setlength{\fboxsep}{0pt}

下面是一个 \verb|\valign| 表格：
\begingroup
% \hsize 控制 \valign 的
% 列宽。我们还设置
% \parindent 为一个较小的值
\hsize=30pt
\parindent=10pt
\fbox{\valign{
#&#&#\cr % 前导部分：稍后会详细介绍！
A&B&C\cr % 这个 \valign 表格的第一列
D&E&F\cr
G&H&I\cr
}}
\endgroup

% 注意：由于后文解释的原因
% \halign 必须放入 \vbox 中
下面是一个 \verb|\halign| 表格：\fbox{%
\vbox{\halign{
#&#&#\cr % 前导部分：稍后会详细介绍！
A&B&C\cr % 这个 \halign 表格的第一行
D&E&F\cr
G&H&I\cr
}}}
\end{document}
```

[在 Overleaf 中打开此示例](https://www.overleaf.com/docs?engine=pdflatex\&snip_name=Basic+table+example\&snip=%5Cdocumentclass%7Barticle%7D%0A%5Cbegin%7Bdocument%7D%0A%5Cpagestyle%7Bempty%7D%0A%25+Close-fitting+box+borders+%0A%5Csetlength%7B%5Cfboxsep%7D%7B0pt%7D%0A%0AHere+is+a+%5Cverb%7C%5Cvalign%7C+table%3A+%0A%5Cbegingroup%0A%25+%5Chsize+controls+the+%5Cvalign+%0A%25+column+widths.+We+also+set+%0A%25+%5Cparindent+to+a+smaller+value%0A%5Chsize%3D30pt+%0A%5Cparindent%3D10pt%0A%5Cfbox%7B%5Cvalign%7B%0A%23%26%23%26%23%5Ccr+%25+The+preamble%3A+covered+later+%28in+great+detail%21%29%0AA%26B%26C%5Ccr+%25+The+first+COLUMN+of+this+%5Cvalign+table%0AD%26E%26F%5Ccr%0AG%26H%26I%5Ccr%0A%7D%7D%0A%5Cendgroup%0A%0A%25+Note%3A+for+reasons+explained+later%0A%25+the+%5Chalign+has+to+be+put+in+a+%5Cvbox%0AHere+is+an+%5Cverb%7C%5Chalign%7C+table%3A+%5Cfbox%7B%25%0A%5Cvbox%7B%5Chalign%7B%0A%23%26%23%26%23%5Ccr+%25+The+preamble%3A+covered+later+%28in+great+detail%21%29%0AA%26B%26C%5Ccr+%25+The+first+ROW+of+this+%5Chalign+table%0AD%26E%26F%5Ccr%0AG%26H%26I%5Ccr%0A%7D%7D%7D%0A%5Cend%7Bdocument%7D)

此示例生成如下输出： ![](/files/cbf1d577a469407bdc2eeda74a8b4a4a91c89d91)

下图展示了由上面代码生成的表格的带注释版本。在本系列文章后面，我们将讨论诸如以下主题：

* 什么是表格前导部分？
* 为什么要设置 `\hsize` 和 `\parindent` 用于 `\valign` 表格？

就当前目的而言，只需注意 `\halign` *与*. `\valign` 表格构造的按行与按列方式：

![](/files/2d1bbcb043eb4acfb4489c7c7ea8edecf7187843)

## \halign 和 \valign 的一般形式

首先，我们将回顾 `\halign` 和 `\valign` 的基本属性和一般格式，但暂不深入任何细节。 [如前所述](#intro)，我们对 `\halign` 和 `\valign` 命令的形式/结构采用一种稍微正式的概览，以为本系列后续文章奠定基础。

最一般的 `\halign` 和 `\valign` 命令形式可写为如下：

`\halign` $$\langle$$⁠`可选规格`⁠$$\rangle$$ { $$\langle$$⁠`导言区`⁠$$\rangle$$ $$\langle$$⁠`主体`⁠$$\rangle$$ }

`\valign` $$\langle$$⁠`可选规格`⁠$$\rangle$$ { $$\langle$$⁠`导言区`⁠$$\rangle$$ $$\langle$$⁠`主体`⁠$$\rangle$$ }

如你所见，两者都 `\halign` 和 `\valign` 由三个主要部分组成：

* [$$\langle$$⁠`可选规格`⁠$$\rangle$$](#optspec)
* [$$\langle$$⁠`导言区`⁠$$\rangle$$](#preamble)
* [$$\langle$$⁠`主体`⁠$$\rangle$$](#body)

## 该 $$\langle$$⁠可选规格⁠$$\rangle$$

表格的默认大小/范围，即所谓的“自然尺寸”，由其内容决定——澄清一下，这里所说的大小/范围指的是

* 该 *宽度* 由……生成的表格的 `\halign`，或
* 该 *高度* 由……生成的表格的 `\valign`

一个 $$\langle$$⁠`可选规格`⁠$$\rangle$$ 可用于“覆盖”表格的自然尺寸，并有两种形式：

* **`更改为`** $$\langle$$**⁠`尺寸`⁠**$$\rangle$$
* **`spread`** $$\langle$$**⁠`尺寸`⁠**$$\rangle$$

其中

* $$\langle$$**⁠`尺寸`⁠**$$\rangle$$ 是以 TeX 可理解的单位给出的长度，例如 pt、mm 或 cm——该长度也可以指定为一个展开后得到相应单位值的命令；
* **`更改为`** 和 **`spread`** 是指定自然尺寸“覆盖”类型的 TeX 关键字：
  * **`更改为`**：将表格的尺寸设为指定的 $$\langle$$⁠`尺寸`⁠$$\rangle$$ 值
  * **`spread`**：将指定的 $$\langle$$⁠`尺寸`⁠$$\rangle$$ 值加到表格的自然尺寸上

一个……的效果 $$\langle$$⁠`可选规格`⁠$$\rangle$$ 取决于正在排版的表格类型：它会调整一个 `\halign` 表格的自然 *宽度*，或一个 `\valign` 表格的自然 *高度*.

下面是一些示例：

* `\halign **to 100pt**{...}`：将 `\halign` 表格的宽度设为 `100pt`
* `\valign **to 50pt**{...}`：将 `\valign` 表格的高度设为 `30pt`
* `\halign **spread 30pt**{...}`：将 30pt 加到 `\halign` 表格的自然宽度上。相反，写成 **spread -30pt** 会使表格宽度减少 30pt。
* `\valign **spread 20pt**{...}`：将 20pt 加到 `\valign` 表格的自然高度上。相反，写成 **spread -20pt** 会使表格高度减少 20pt。

下面的代码重用了上面的表格示例，但对一个 $$\langle$$⁠`可选规格`⁠$$\rangle$$ 应用了 `\valign` 和 `\halign` 表格：

```latex
\documentclass{article}
\begin{document}
\pagestyle{empty}
% 紧贴的盒子边框
\setlength{\fboxsep}{0pt}

下面是一个 \verb|\valign| 表格：
\begingroup
\hsize=30pt
\parindent=10pt
\fbox{\valign to 50pt{
#&#&#\cr
A&B&C\cr
D&E&F\cr
G&H&I\cr
}}
\endgroup

下面是一个 \verb|\halign| 表格：
\fbox{%
\vbox{\halign to 100pt{
#&#&#\cr
A&B&C\cr
D&E&F\cr
G&H&I\cr
}}}
\end{document}
```

[在 Overleaf 中打开此示例](https://www.overleaf.com/docs?engine=pdflatex\&snip_name=Basic+table+example\&snip=%5Cdocumentclass%7Barticle%7D%0A%5Cbegin%7Bdocument%7D%0A%5Cpagestyle%7Bempty%7D%0A%25+Close-fitting+box+borders+%0A%5Csetlength%7B%5Cfboxsep%7D%7B0pt%7D%0A%0AHere+is+a+%5Cverb%7C%5Cvalign%7C+table%3A+%0A%5Cbegingroup%0A%5Chsize%3D30pt+%0A%5Cparindent%3D10pt%0A%5Cfbox%7B%5Cvalign+to+50pt%7B%0A%23%26%23%26%23%5Ccr%0AA%26B%26C%5Ccr%0AD%26E%26F%5Ccr%0AG%26H%26I%5Ccr%0A%7D%7D%0A%5Cendgroup%0A%0AHere+is+an+%5Cverb%7C%5Chalign%7C+table%3A%0A%5Cfbox%7B%25%0A%5Cvbox%7B%5Chalign+to+100pt%7B%0A%23%26%23%26%23%5Ccr%0AA%26B%26C%5Ccr%0AD%26E%26F%5Ccr%0AG%26H%26I%5Ccr%0A%7D%7D%7D%0A%5Cend%7Bdocument%7D)

该示例生成如下所示的输出：

![](/files/91ca42dd60e11c933f992f9e233a82cf13219e5d)

——但请注意，这两个表格的内容是如何“挤在一起”的。原因在于缺少 TeX 可用于拉伸内容以填充由……提供的额外空间的弹性间距（glue） **`更改为`** $$\langle$$**⁠`尺寸`⁠**$$\rangle$$。这里我们先提前提及 `\tabskip` 该命令。

#### \tabskip 命令的初步介绍

表格布局的美观性可能需要调整行或列之间的间距，因此 TeX 引擎自然提供了一个名为 `\tabskip` 的命令来实现这一点。 `\tabskip` 用于设置（并变化）TeX 在一个……的列之间放置的弹性空间（“glue”）量 `\halign` 或一个……的行之间的弹性空间量 `\valign`。后面的文章将探讨 `\tabskip` ，并更详细地讨论。

作为一个入门示例，下面的代码使用了一个 `\tabskip` ，这会使 TeX 在一个……的行之间插入一些（非常）弹性的空间 `\valign` 表格。该弹性空间使表格各行能够展开并填充由……产生的额外空间 $$\langle$$⁠`可选规格`⁠$$\rangle$$ 的记号值 **`to 50pt`**:

```latex
\documentclass{article}
\setlength{\fboxsep}{0pt}
\setlength{\parindent}{0pt}
\newcommand{\optspec}{\(\langle \texttt{optional specification} \rangle\)}
\begin{document}
\pagestyle{empty}
下面是一个 \verb|\valign| 表格：
\vspace{6pt}

\begingroup
\hsize=30pt
\parindent=10pt
\fbox{\valign{
#&#&#\cr
A&B&C\cr
D&E&F\cr
G&H&I\cr
}}
\endgroup
\vspace{6pt}

下面是相同的 \verb|\valign| 表格，但其 \optspec{} 为 ``\texttt{to 50pt}''。请注意，各行是如何“挤在一起”的，因为行之间没有可用的“可伸缩 glue”：

\vspace{6pt}
\begingroup
\hsize=30pt
\parindent=10pt
\fbox{\valign to 50pt{
#&#&#\cr
A&B&C\cr
D&E&F\cr
G&H&I\cr
}}
\endgroup
\vspace{6pt}

我们将使用 \optspec{} 为 ``\texttt{to 50pt}'' 的 \verb|\valign| 表格，但通过 \verb|\tabskip| 命令提供“弹性间距”。这里，\verb|\tabskip| 提供了足够的“glue”，使 \verb|\valign| 的各行能够“拉伸”并填充任何可用的额外空间。下面是“拉伸后”的 \verb|\valign| 表格：

\tabskip=0pt plus1fil % 这将 \tabskip 设为一个非常弹性的 glue
\vspace{6pt}

\def\mylen{50pt}
\begingroup
\hsize=30pt
\parindent=10pt
\fbox{\valign to \mylen{
#&#&#\cr
A&B&C\cr
D&E&F\cr
G&H&I\cr
}}
\endgroup
\end{document}
```

[在 Overleaf 中打开此示例](https://www.overleaf.com/docs?engine=pdflatex\&snip_name=Basic+example+using+tabskip+glue\&snip=%5Cdocumentclass%7Barticle%7D%0A%5Csetlength%7B%5Cfboxsep%7D%7B0pt%7D%0A%5Csetlength%7B%5Cparindent%7D%7B0pt%7D%0A%5Cnewcommand%7B%5Coptspec%7D%7B%5C%28%5Clangle+%5Ctexttt%7Boptional+specification%7D+%5Crangle%5C%29%7D%0A%5Cbegin%7Bdocument%7D%0A%5Cpagestyle%7Bempty%7D%0AHere+is+a+%5Cverb%7C%5Cvalign%7C+table%3A%0A%5Cvspace%7B6pt%7D%0A%0A%5Cbegingroup%0A%5Chsize%3D30pt+%0A%5Cparindent%3D10pt%0A%5Cfbox%7B%5Cvalign%7B%0A%23%26%23%26%23%5Ccr%0AA%26B%26C%5Ccr%0AD%26E%26F%5Ccr%0AG%26H%26I%5Ccr%0A%7D%7D%0A%5Cendgroup%0A%5Cvspace%7B6pt%7D%0A%0AHere+is+the+same+%5Cverb%7C%5Cvalign%7C+table+but+with+an+%5Coptspec%7B%7D+of+%60%60%5Ctexttt%7Bto+50pt%7D%27%27.+Note+how+the+rows+are+%60%60bunched+up%27%27+because+there%27s+no+available+%60%60stretchable+glue%27%27+between+the+rows%3A+%0A%0A%5Cvspace%7B6pt%7D%0A%5Cbegingroup%0A%5Chsize%3D30pt+%0A%5Cparindent%3D10pt%0A%5Cfbox%7B%5Cvalign+to+50pt%7B%0A%23%26%23%26%23%5Ccr%0AA%26B%26C%5Ccr%0AD%26E%26F%5Ccr%0AG%26H%26I%5Ccr%0A%7D%7D%0A%5Cendgroup%0A%5Cvspace%7B6pt%7D%0A%0AWe%27ll+use+the+%5Cverb%7C%5Cvalign%7C+table+with+%5Coptspec%7B%7D+of+%60%60%5Ctexttt%7Bto+50pt%7D%27%27%2C+but+provide+%60%60flexible+spacing%27%27+via+the+%5Cverb%7C%5Ctabskip%7C+command.+Here%2C+%5Cverb%7C%5Ctabskip%7C+is+providing+enough+%60%60glue%27%27+to+enable+the++%5Cverb%7C%5Cvalign%7C+rows+to++%60%60stretch+out%27%27+and+fill+any+available+extra+space.+Here+is+the+%60%60stretched+out%27%27+%5Cverb%7C%5Cvalign%7C+table%3A%0A%0A%5Ctabskip%3D0pt+plus1fil+%25+This+sets+%5Ctabskip+to+a+very+flexible+glue%0A%5Cvspace%7B6pt%7D%0A%0A%5Cdef%5Cmylen%7B50pt%7D%0A%5Cbegingroup%0A%5Chsize%3D30pt+%0A%5Cparindent%3D10pt%0A%5Cfbox%7B%5Cvalign+to+%5Cmylen%7B%0A%23%26%23%26%23%5Ccr%0AA%26B%26C%5Ccr%0AD%26E%26F%5Ccr%0AG%26H%26I%5Ccr%0A%7D%7D%0A%5Cendgroup%0A%5Cend%7Bdocument%7D)

此示例生成如下输出：

![](/files/5a139bbb4990b03a2a27d0ed1de5d21e84643a21)

## 介绍表格的 $$\langle$$⁠前导部分⁠$$\rangle$$ 和 $$\langle$$⁠主体⁠$$\rangle$$

本节介绍表格的 $$\langle$$⁠`导言区`⁠$$\rangle$$，以及 *简要地* 涉及表格的 $$\langle$$⁠`主体`⁠$$\rangle$$ 随后 [会更详细地探讨](#bodydetails).

本系列后续文章将探讨 $$\langle$$⁠`导言区`⁠$$\rangle$$ 和 $$\langle$$⁠`主体`⁠$$\rangle$$ ，尤其是 TeX 对表格的使用和处理 $$\langle$$⁠`导言区`⁠$$\rangle$$.

如上所述，最一般的 `\halign` 或 `\valign` 表格格式可写为：

`\halign` $$\langle$$⁠`可选规格`⁠$$\rangle$$ { $$\langle$$⁠`导言区`⁠$$\rangle$$ $$\langle$$⁠`主体`⁠$$\rangle$$ }

`\valign` $$\langle$$⁠`可选规格`⁠$$\rangle$$ { $$\langle$$⁠`导言区`⁠$$\rangle$$ $$\langle$$⁠`主体`⁠$$\rangle$$ }

### 该 $$\langle$$⁠前导部分⁠$$\rangle$$

该 $$\langle$$⁠`导言区`⁠$$\rangle$$ 部分包含一条单独的 $$\langle$$⁠`前导行`⁠$$\rangle$$ ，该文档是 *结束于* 由……的 `\cr` 命令；因此， $$\langle$$⁠`导言区`⁠$$\rangle$$ 可改写为：

$$\langle$$⁠`导言区`⁠$$\rangle$$=$$\langle$$⁠`前导行`⁠$$\rangle$$**`\cr`**

### 该 $$\langle$$⁠主体⁠$$\rangle$$

同样， $$\langle$$⁠主体⁠$$\rangle$$ 部分还可以进一步分解为一条或多条组成“行”，但这里每一行有两种选项：

* 由一组单元格组成的一行，这些单元格形成一个 `\halign` 行或 `\valign` 列；或
* a `\noalign` 会在一个……之间“注入”材料的命令 `\halign`的行或 `\valign`的列之间。

就当前目的而言，我们将忽略 `\noalign` 命令（见 [本文后面部分](#noalign)）并假设 $$\langle$$⁠主体⁠$$\rangle$$ 的每一行都是一组单元格的数据，并由 *结束于* 通过 `\cr` 该命令。

忽略 `\noalign`， $$\langle$$⁠`主体`⁠$$\rangle$$ 部分（表示用户内容）包含一系列行，我们将把每一行称为一个 $$\langle$$⁠`主体行`⁠$$\rangle$$ 其 *结束于* 由其相应的 `\cr` 该命令。

该 $$\langle$$⁠`主体`⁠$$\rangle$$ 可改写为：

$$\langle$$⁠主体行$${}\_1$$⁠$$\rangle$$\cr $$\langle$$⁠主体行$${}\_2$$⁠$$\rangle$$\cr $$\langle$$⁠主体行$${}*3$$⁠$$\rangle$$\cr ... $$\langle$$⁠主体行$${}*\mathrm{N}$$⁠$$\rangle$$\cr

综合起来，我们可以将 `\halign` 和 `\valign` 为：

`\halign` $$\langle$$⁠`可选规格`⁠$$\rangle$$ { $$\langle$$⁠`前导行`⁠$$\rangle$$\cr $$\langle$$⁠主体行$${}\_1$$⁠$$\rangle$$\cr $$\langle$$⁠主体行$${}\_2$$⁠$$\rangle$$\cr $$\langle$$⁠主体行$${}*3$$⁠$$\rangle$$\cr ... $$\langle$$⁠主体行$${}*\mathrm{N}$$⁠$$\rangle$$\cr }

`\valign` $$\langle$$⁠`可选规格`⁠$$\rangle$$ { $$\langle$$⁠`前导行`⁠$$\rangle$$\cr $$\langle$$⁠主体行$${}\_1$$⁠$$\rangle$$\cr $$\langle$$⁠主体行$${}\_2$$⁠$$\rangle$$\cr $$\langle$$⁠主体行$${}*3$$⁠$$\rangle$$\cr ... $$\langle$$⁠主体行$${}*\mathrm{N}$$⁠$$\rangle$$\cr }

由于后续文章中将要说明的原因， $$\langle$$⁠`导言区`⁠$$\rangle$$，仅单独一个 $$\langle$$⁠`前导行`⁠$$\rangle$$，其格式与表格中的所有其他行都不同 $$\langle$$⁠`主体`⁠$$\rangle$$。我们还将 [重新讨论 `\noalign` 命令](#noalign) ，它也可在表格中使用 $$\langle$$⁠`主体`⁠$$\rangle$$.

### 该 $$\langle$$⁠前导行⁠$$\rangle$$

该 $$\langle$$⁠`前导行`⁠$$\rangle$$ 起着 *至关重要的* 作用，因为它提供了一种用于排版内容的“蓝图”——`\halign` 行或 `\valign` 列— $$\langle$$⁠`主体`⁠$$\rangle$$。 $$\langle$$⁠`前导行`⁠$$\rangle$$ 还可以包含单元格“模板”，用于构造一个……的各行 `\halign` 或一个……的各列 `\valign`——这是一个将详细探讨的话题。

该……的目的 $$\langle$$⁠`前导行`⁠$$\rangle$$ 是双重的：

* 它决定 *最大值* 一个……每行的单元格数量 `\halign` 或一个……每列的单元格数量 `\valign`.
* 它存储 *单元格模板* 这些模板可用于自动化格式化或在表格中的单元格内包含内容 $$\langle$$⁠`主体`⁠$$\rangle$$。单元格模板是可选的，也可以是“空”的；或者你可以包含一些字符或命令，让 TeX 自动在表格中特定单元格的实际内容之前和/或之后插入它们。这样可以省去你必须手动在每个希望适用的单元格中写入/包含这些字符或命令的麻烦。

**注意**：一个 `\halign` 行或 `\valign` 列可以包含少于由……指定的最大值的单元格 $$\langle$$⁠`前导行`⁠$$\rangle$$ 但不能超过该最大值，否则 TeX 会报错。就当前目的而言，我们省略 *循环* 前导部分的细节。

继续看我们的结构图， $$\langle$$⁠`前导行`⁠$$\rangle$$ 用于

* 一个 `\halign` 具有最大……个的表格 $$\mathrm{K}$$ 每……个单元格 *行*，或
* a `\valign` 具有最大……个的表格 $$\mathrm{K}$$ 每……个单元格 *列*

可写为：

$$\langle$$⁠模板$${}\_1$$⁠$$\rangle$$&$$\langle$$⁠模板$${}\_2$$⁠$$\rangle$$&$$\langle$$⁠模板$${}*3$$⁠$$\rangle$$ $$\cdots$$ &$$\langle$$⁠模板$${}*\mathrm{K}$$⁠$$\rangle$$

其中 `&` 是 *对齐制表符字符* 它表示一个单元格的结束和下一个单元格的开始。传统上，和号字符（`&`）被用作对齐制表符，但任何具有 [类别码](/latex/zh-cn/geng-duo-zhu-ti/43-table-of-tex-category-codes.md) 4 的字符

作为提醒， $$\langle$$⁠`导言区`⁠$$\rangle$$ 可写作 $$\langle$$⁠`导言区`⁠$$\rangle$$=$$\langle$$⁠`前导行`⁠$$\rangle$$**`\cr`**，或者等价地

$$\langle$$⁠`导言区`⁠$$\rangle$$=$$\langle$$⁠模板$${}\_1$$⁠$$\rangle$$&$$\langle$$⁠模板$${}\_2$$⁠$$\rangle$$&$$\langle$$⁠模板$${}*3$$⁠$$\rangle$$ $$\cdots$$ &$$\langle$$⁠模板$${}*\mathrm{K}$$⁠$$\rangle$$**`\cr`**

#### 每个单元格的结构 $$\langle$$⁠模板⁠$$\rangle$$

每个单元格 $$\langle$$⁠模板$${}\_i$$⁠$$\rangle$$ 可写为：

$$\langle$$⁠$$\texttt{U}\_i$$⁠$$\rangle$$$$\texttt{#}$$$$\langle$$⁠$$\texttt{V}\_i$$⁠$$\rangle$$ 其中：

* $$\langle$$⁠$$\texttt{U}\_i$$⁠$$\rangle$$ 是一组 TeX 会自动插入的字符或命令（记号） *在* 单元格的用户提供内容 $$i$$;
* $$\texttt{#}$$ 是一个占位符，显示用户提供的内容将出现在单元格中的位置 $$i$$。同样， `#` 字符只是一个 *传统*，任何具有 [类别码](/latex/zh-cn/geng-duo-zhu-ti/43-table-of-tex-category-codes.md) 6 的字符都可以代替。请注意，类别码 6 用于宏参数；
* $$\langle$$⁠$$\texttt{V}\_i$$⁠$$\rangle$$ 是一组 TeX 会自动插入的字符或命令（记号） *在* 单元格的用户提供内容 $$i$$.

请注意，所有 $$\langle$$⁠$$\texttt{U}\_i$$⁠$$\rangle$$ 和 $$\langle$$⁠$$\texttt{V}\_i$$⁠$$\rangle$$ 已 *可选的*：你不必在单元格内容之前或之后使用任何字符或命令。

**完成** $$\langle$$**⁠前导部分⁠**$$\rangle$$

最后，使用上面的记法， $$\langle$$⁠`导言区`⁠$$\rangle$$ 用于

* 一个 `\halign` 具有最大……个的表格 $$\mathrm{K}$$ 每……个单元格 *行*，或
* a `\valign` 具有最大……个的表格 $$\mathrm{K}$$ 每……个单元格 *列*

可写为：

$$\langle$$⁠`导言区`⁠$$\rangle$$=$$\langle$$⁠`前导行`⁠$$\rangle$$`**\cr**`

或

$$\langle$$⁠`导言区`⁠$$\rangle$$=$$\langle$$⁠$$\texttt{U}\_1$$⁠$$\rangle$$$$\texttt{#}$$$$\langle$$⁠$$\texttt{V}\_1$$⁠$$\rangle$$&$$\langle$$⁠$$\texttt{U}\_2$$⁠$$\rangle$$$$\texttt{#}$$$$\langle$$⁠$$\texttt{V}\_2$$⁠$$\rangle$$&$$\langle$$⁠$$\texttt{U}*3$$⁠$$\rangle$$$$\texttt{#}$$$$\langle$$⁠$$\texttt{V}*3$$⁠$$\rangle$$$$\cdots$$$$\langle$$⁠$$\texttt{U}*\mathrm{K}$$⁠$$\rangle$$$$\texttt{#}$$$$\langle$$⁠$$\texttt{V}*\mathrm{K}$$⁠$$\rangle$$`**\cr**`

**该** $$\langle$$**⁠前导部分⁠**$$\rangle$$ **以及行和列的计数**

一个 **`\halign`** 具有一个……的表格 $$\langle$$⁠`导言区`⁠$$\rangle$$ 指定 $$\mathrm{K}$$ 单元格，以及一个 $$\langle$$⁠`主体`⁠$$\rangle$$ 包含 $$\mathrm{N}$$ $$\langle$$⁠`主体行`⁠$$\rangle$$ 将生成一个具有 $$\mathrm{K}$$ *列* 和 $$\mathrm{N}$$ *行*，如下图所示：

![](/files/8ef9a626470dde5ffcbdc0d6909cadd22ccd74c9)

一个 **`\valign`** 具有一个……的表格 $$\langle$$⁠`导言区`⁠$$\rangle$$ 指定 $$\mathrm{K}$$ 单元格，以及一个 $$\langle$$⁠`主体`⁠$$\rangle$$ 包含 $$\mathrm{N}$$ $$\langle$$⁠`主体行`⁠$$\rangle$$ 将生成一个具有 $$\mathrm{K}$$ *行* 和 $$\mathrm{N}$$ *列*，如下图所示：

![](/files/33515e0c902d598ef2f5d25198472c2980219d2c)

### 理论够了，来看几个例子！

正如我们稍后将详细看到的，当 TeX 处理表格内容——即包含在……中的表格单元格时 [$$\langle$$⁠`主体`⁠$$\rangle$$](#body)——它会检查是否存在单元格模板，这些模板定义在 $$\langle$$⁠`导言区`⁠$$\rangle$$，因为 TeX 要查找任何要插入到用户内容之前和/或之后的模板记号。下面这些最小示例演示了单元格模板的使用 $$\langle$$⁠$$\texttt{U}\_i$$⁠$$\rangle$$$$\texttt{#}$$$$\langle$$⁠$$\texttt{V}\_i$$⁠$$\rangle$$ 在一个 `\halign` 和 `\valign` 表格的 SVG 图形。

#### 使用单元格模板的 \halign 表格

下面的示例演示了一个 `\halign` 该表格使用单元格模板在每一行第一个单元格内容周围自动插入双引号：也就是说，一个影响第一列每个单元格的模板：

```latex
\documentclass{article}
\usepackage{parskip} % 将 \parindent 设为 0pt
% 选择一个方便的小页面尺寸
\usepackage[paperheight=10cm,paperwidth=12cm,textwidth=8cm]{geometry}
\setlength{\tabskip}{20pt} % 增加 \halign 各列之间的间距
\begin{document}
\pagestyle{empty}

下面是一个 \verb|\halign| 表格，\textit{不使用}单元格模板：

\halign{
% 在 <preamble> 中每个 '#' 的前后都不加任何内容
#&#&#\cr
A&B&C\cr
D&E&F\cr
G&H&I\cr
}

下面是同一个 \verb|\halign| 表格，但会在每一行的第一个单元格自动添加双引号；也就是说，它影响第一列中的每个单元格：

\halign{
% 前导部分中的引号模板：
``#''&#&#\cr % 在第一个 # 前后添加双引号
A&B&C\cr
D&E&F\cr
G&H&I\cr
}
\end{document}
```

[在 Overleaf 中打开此示例](https://www.overleaf.com/docs?engine=pdflatex\&snip_name=halign+example+of+cell+templates\&snip=%5Cdocumentclass%7Barticle%7D%0A%5Cusepackage%7Bparskip%7D+%25+Set+%5Cparindent+to+0pt%0A%25+Choose+a+conveniently+small+page+size%0A%5Cusepackage%5Bpaperheight%3D10cm%2Cpaperwidth%3D12cm%2Ctextwidth%3D8cm%5D%7Bgeometry%7D%0A%5Csetlength%7B%5Ctabskip%7D%7B20pt%7D+%25+Space+out+the+%5Chalign+columns%0A%5Cbegin%7Bdocument%7D%0A%5Cpagestyle%7Bempty%7D%0A%0AHere+is+an+%5Cverb%7C%5Chalign%7C+table+%5Ctextit%7Bwithout%7D+cell+templates%3A+%0A%0A%5Chalign%7B%0A%25+Nothing+before+or+after+each+%27%23%27+in+the+%3Cpreamble%3E%0A%23%26%23%26%23%5Ccr+%0AA%26B%26C%5Ccr%0AD%26E%26F%5Ccr%0AG%26H%26I%5Ccr%0A%7D%0A%0AHere+is+the+same+%5Cverb%7C%5Chalign%7C+table+but+with+double+quotes+automatically+added+to+the+first+cell+in+each+row%3B+i.e.%2C+it+affects+every+cell+in+the+first+column%3A+%0A%0A%5Chalign%7B%0A%25+Quotation+templates+in+the+preamble%3A%0A%60%60%23%27%27%26%23%26%23%5Ccr+%25+Double+quote+marks+before+and+after+first+%23%0AA%26B%26C%5Ccr%0AD%26E%26F%5Ccr%0AG%26H%26I%5Ccr%0A%7D%0A%5Cend%7Bdocument%7D)

此示例生成如下输出：

![](/files/dd2c467b4b83248e099da6d9893380f4ddeff374)

下图是……的带注释版本 `\halign` 由上面示例生成的表格；这里我们比较一个三单元格 $$\langle$$⁠`导言区`⁠$$\rangle$$:

$$\langle$$⁠$$\texttt{U}\_1$$⁠$$\rangle$$$$\texttt{#}$$$$\langle$$⁠$$\texttt{V}\_1$$⁠$$\rangle$$&$$\langle$$⁠$$\texttt{U}\_2$$⁠$$\rangle$$$$\texttt{#}$$$$\langle$$⁠$$\texttt{V}\_2$$⁠$$\rangle$$&$$\langle$$⁠$$\texttt{U}\_3$$⁠$$\rangle$$$$\texttt{#}$$$$\langle$$⁠$$\texttt{V}\_3$$⁠$$\rangle$$`**\cr**`

的“形式”结构与实际的 $$\langle$$⁠`导言区`⁠$$\rangle$$ 的记号值 ` ``#''&#&#**\cr** `，突出显示单元格模板的存在或缺失：

![](/files/a8167d7f00836069b0ada086c4658167b933998e)

#### 使用单元格模板的 \valign 表格

下面的示例演示了一个 `\valign` 该表格为每个单元格使用一个模板，以在用户内容的周围自动插入数字。

```latex
\documentclass{article}
\usepackage{parskip} % 将 \parindent 设为 0pt
% 选择一个方便的小页面尺寸
\usepackage[paperheight=14cm,paperwidth=12cm,textwidth=10cm]{geometry}
\setlength{\tabskip}{8pt} % 增加 \valign 各行之间的间距
\begin{document}
\pagestyle{empty}

下面是一个 \verb|\valign| 表格，\textit{不使用}单元格模板：

\begingroup
\hsize=25pt
\valign{
% 在每个 '#' 的前后都不加任何内容
% <preamble> 中
#&#&#\cr
A&B&C\cr
D&E&F\cr
G&H&I\cr
}
\endgroup

下面是同一个 \verb|\valign| 表格，但使用单元格模板在每个单元格中自动插入数字：

\begingroup
\hsize=25pt
\valign{
% 在每个 '#' 的前后插入数字
% <preamble> 中
1#2&3#4&5#6\cr
A&B&C\cr
D&E&F\cr
G&H&I\cr
}
\endgroup
\end{document}
```

[在 Overleaf 中打开此示例](https://www.overleaf.com/docs?engine=pdflatex\&snip_name=Example+of+valign+cell+templates\&snip=%5Cdocumentclass%7Barticle%7D%0A%5Cusepackage%7Bparskip%7D+%25+Set+%5Cparindent+to+0pt%0A%25+Choose+a+conveniently+small+page+size%0A%5Cusepackage%5Bpaperheight%3D14cm%2Cpaperwidth%3D12cm%2Ctextwidth%3D10cm%5D%7Bgeometry%7D%0A%5Csetlength%7B%5Ctabskip%7D%7B8pt%7D+%25+Space+out+the+%5Cvalign+rows%0A%5Cbegin%7Bdocument%7D%0A%5Cpagestyle%7Bempty%7D%0A%0AHere+is+a+%5Cverb%7C%5Cvalign%7C+table+%5Ctextit%7Bwithout%7D+cell+templates%3A%0A%0A%5Cbegingroup%0A%5Chsize%3D25pt%0A%5Cvalign%7B%0A%25+Nothing+before+or+after+each+%27%23%27+in+%0A%25+the+%3Cpreamble%3E%0A%23%26%23%26%23%5Ccr+%0AA%26B%26C%5Ccr%0AD%26E%26F%5Ccr%0AG%26H%26I%5Ccr%0A%7D%0A%5Cendgroup%0A%0AHere+is+the+same+%5Cverb%7C%5Cvalign%7C+table+but+using+cell+templates+to+automatically+insert+digits+into+every+cell%3A+%0A%0A%5Cbegingroup%0A%5Chsize%3D25pt%0A%5Cvalign%7B%0A%25+Digits+inserted+before+and+after+every+%27%23%27+in%0A%25+the+%3Cpreamble%3E%0A1%232%263%234%265%236%5Ccr+%0AA%26B%26C%5Ccr%0AD%26E%26F%5Ccr%0AG%26H%26I%5Ccr%0A%7D%0A%5Cendgroup%0A%5Cend%7Bdocument%7D)

此示例生成如下输出：

![](/files/ad7ec42019beb44ee651df2f9142ada3947fcc0c)

下图是……的带注释版本 `\valign` 由上面示例生成的表格；这里我们比较一个三单元格 $$\langle$$⁠`导言区`⁠$$\rangle$$:

$$\langle$$⁠$$\texttt{U}\_1$$⁠$$\rangle$$$$\texttt{#}$$$$\langle$$⁠$$\texttt{V}\_1$$⁠$$\rangle$$&$$\langle$$⁠$$\texttt{U}\_2$$⁠$$\rangle$$$$\texttt{#}$$$$\langle$$⁠$$\texttt{V}\_2$$⁠$$\rangle$$&$$\langle$$⁠$$\texttt{U}\_3$$⁠$$\rangle$$$$\texttt{#}$$$$\langle$$⁠$$\texttt{V}\_3$$⁠$$\rangle$$`**\cr**`

的“形式”结构与实际的 $$\langle$$⁠`导言区`⁠$$\rangle$$ 的记号值 `1#2&3#4&5#6**\cr**`，突出显示单元格模板的使用 $$\langle$$⁠$$\texttt{U}\_i$$⁠$$\rangle$$$$\texttt{#}$$$$\langle$$⁠$$\texttt{V}\_i$$⁠$$\rangle$$:

![](/files/f0572d17c09f4be1bd97e42474a5edeee33fa7b9)

请注意单元格 $$i$$ ($$\langle$$⁠$$\texttt{U}\_i$$⁠$$\rangle$$$$\texttt{#}$$$$\langle$$⁠$$\texttt{V}\_i$$⁠$$\rangle$$）的模板如何应用于 $$i$$第……个单元格在每个 `\valign` 列，从而使……中的所有单元格都 $$i$$第……个 *行* 受到影响。

#### 使用单元格模板设置文本样式

接下来的示例使用以下 $$\langle$$⁠`导言区`⁠$$\rangle$$ （单元格模板）来设置每行或每列中所包含文本的样式：

`\textbf{#}&\textit{#}&\texttt{#}\cr`

如果我们将这 $$\langle$$⁠`导言区`⁠$$\rangle$$ 与我们的三单元格“形式”结构进行比较 $$\langle$$⁠`导言区`⁠$$\rangle$$:

$$\langle$$⁠$$\texttt{U}\_1$$⁠$$\rangle$$$$\texttt{#}$$$$\langle$$⁠$$\texttt{V}\_1$$⁠$$\rangle$$&$$\langle$$⁠$$\texttt{U}\_2$$⁠$$\rangle$$$$\texttt{#}$$$$\langle$$⁠$$\texttt{V}\_2$$⁠$$\rangle$$&$$\langle$$⁠$$\texttt{U}\_3$$⁠$$\rangle$$$$\texttt{#}$$$$\langle$$⁠$$\texttt{V}\_3$$⁠$$\rangle$$`**\cr**`

我们可以看到：

$$\langle$$⁠$$\texttt{U}\_1$$⁠$$\rangle$$=`\textbf{`

$$\langle$$⁠$$\texttt{V}\_1$$⁠$$\rangle$$=`}`

$$\langle$$⁠$$\texttt{U}\_2$$⁠$$\rangle$$=`\textit{`

$$\langle$$⁠$$\texttt{V}\_2$$⁠$$\rangle$$=`}`

$$\langle$$⁠$$\texttt{U}\_3$$⁠$$\rangle$$=`\texttt{`

$$\langle$$⁠$$\texttt{V}\_3$$⁠$$\rangle$$=`}`

注意这些单元格模板，例如 `\textbf{#}` 类似于带一个参数（单元格内容）的宏。

```latex
一个使用单元格模板设置文本样式的 \verb|\valign| 表：

\begingroup
\hsize=25pt
\valign{
\textbf{#}&\textit{#}&\texttt{#}\cr
A&B&C\cr
D&E&F\cr
G&H&I\cr
}
\endgroup

一个使用单元格模板设置文本样式的 \verb|\halign| 表：

\halign{
\textbf{#}&\textit{#}&\texttt{#}\cr
A&B&C\cr
D&E&F\cr
G&H&I\cr
}
```

[在 Overleaf 中打开此示例](https://www.overleaf.com/docs?engine=pdflatex\&snip_name=Styling+with+cell+templates\&snip=%5Cdocumentclass%7Barticle%7D%0A%5Cusepackage%7Bparskip%7D+%25+Set+%5Cparindent+to+0pt%0A%25+Choose+a+conveniently+small+page+size%0A%5Cusepackage%5Bpaperheight%3D14cm%2Cpaperwidth%3D12cm%2Ctextwidth%3D6cm%5D%7Bgeometry%7D%0A%25+Space+out+the+%5Chalign+columns+or+%5Cvalign+rows%0A%5Csetlength%7B%5Ctabskip%7D%7B8pt%7D%0A%5Cbegin%7Bdocument%7D%0A%5Cpagestyle%7Bempty%7D%0AA+%5Cverb%7C%5Cvalign%7C+table+with+text+styled+using+cell+templates%3A%0A%0A%5Cbegingroup%0A%5Chsize%3D25pt%0A%5Cvalign%7B%0A%5Ctextbf%7B%23%7D%26%5Ctextit%7B%23%7D%26%5Ctexttt%7B%23%7D%5Ccr+%0AA%26B%26C%5Ccr%0AD%26E%26F%5Ccr%0AG%26H%26I%5Ccr%0A%7D%0A%5Cendgroup%0A%0AAn+%5Cverb%7C%5Chalign%7C+table+with+text+styled+using+cell+templates%3A%0A%0A%5Chalign%7B%0A%5Ctextbf%7B%23%7D%26%5Ctextit%7B%23%7D%26%5Ctexttt%7B%23%7D%5Ccr+%0AA%26B%26C%5Ccr%0AD%26E%26F%5Ccr%0AG%26H%26I%5Ccr%0A%7D%0A%5Cend%7Bdocument%7D)

此示例生成如下输出：

![](/files/0220eee2881ff556243a52ea44524cdf7c3eb28b)

## 更多关于表格的内容 $$\langle$$⁠主体⁠$$\rangle$$

在……部分 [介绍表格的 $$\langle$$⁠`导言区`⁠$$\rangle$$ 和 $$\langle$$⁠`主体`⁠$$\rangle$$](#preamble) 我们看到了，如果我们暂时忽略 `\noalign`， $$\langle$$⁠`主体`⁠$$\rangle$$ 一个……的 `\halign` 或 `\valign` 表由多行组成，每一行都被指定为 $$\langle$$⁠主体行$${}\_j$$⁠$$\rangle$$，其中：

* 每个 $$\langle$$⁠主体行$${}\_j$$⁠$$\rangle$$ 由……终止 `\cr` 命令
* 每个 $$\langle$$⁠主体行$${}\_j$$⁠$$\rangle$$ 一个……的 `\halign` 是一行表格
* 每个 $$\langle$$⁠主体行$${}\_j$$⁠$$\rangle$$ 一个……的 `\valign` 是一列表格

这些行的序列， $$\langle$$⁠主体行$${}\_j$$⁠$$\rangle$$，其中 $$j=1\ldots\mathrm{N}$$，产生 $$\mathrm{N}$$ ……的行 `\halign` 或 $$\mathrm{N}$$ ……的列 `\valign`。如下图所总结，一个通用的 $$\langle$$⁠`导言区`⁠$$\rangle$$ 例如

$$\langle$$⁠`导言区`⁠$$\rangle$$=$$\langle$$⁠$$\texttt{U}\_1$$⁠$$\rangle$$$$\texttt{#}$$$$\langle$$⁠$$\texttt{V}\_1$$⁠$$\rangle$$&$$\langle$$⁠$$\texttt{U}\_2$$⁠$$\rangle$$$$\texttt{#}$$$$\langle$$⁠$$\texttt{V}\_2$$⁠$$\rangle$$&$$\langle$$⁠$$\texttt{U}*3$$⁠$$\rangle$$$$\texttt{#}$$$$\langle$$⁠$$\texttt{V}*3$$⁠$$\rangle$$$$\cdots$$$$\langle$$⁠$$\texttt{U}*\mathrm{K}$$⁠$$\rangle$$$$\texttt{#}$$$$\langle$$⁠$$\texttt{V}*\mathrm{K}$$⁠$$\rangle$$`**\cr**`

为最多 $$\mathrm{K}$$ 每个……中的单元格 $$\mathrm{N}$$ $$\langle$$⁠`主体行`⁠$$\rangle$$ ……中的条目 $$\langle$$⁠`主体`⁠$$\rangle$$:

![](/files/84f23b09596e339b5384ff88c653369653147ef8)

### 每个……的结构 $$\langle$$⁠主体行$${}\_j$$⁠$$\rangle$$

每一行 $$\langle$$⁠主体行$${}\_j$$⁠$$\rangle$$ 表格的 $$\langle$$⁠主体⁠$$\rangle$$ 可包含最多 $$\mathrm{K}$$ 个单元格——由表格 $$\langle$$⁠前导部分⁠$$\rangle$$——其一般形式为：

$$\langle$$⁠主体行$${}\_j$$⁠$$\rangle$$=$$\langle$$⁠单元格$${}\_1$$⁠$$\rangle$$$$\texttt{&}$$$$\langle$$⁠单元格$${}\_2$$⁠$$\rangle$$$$\texttt{&}$$$$\langle$$⁠单元格$${}*3$$⁠$$\rangle$$$$\texttt{&}$$$$\cdots$$$$\texttt{&}$$$$\langle$$⁠单元格$${}*\mathrm{K}$$⁠$$\rangle$$`**\cr**`

其中：

* $$\langle$$⁠单元格$${}\_i$$⁠$$\rangle$$ 表示用户对该 $$i$$个单元格中的第 $$\langle$$⁠主体行$${}\_j$$⁠$$\rangle$$
* 该 **`&`** 字符称为 *对齐制表符* （与 $$\langle$$⁠前导部分⁠$$\rangle$$中使用的相同），它标志着一个单元格的结束和下一个单元格的开始。再次说明，使用 **`&`** 只是一个传统（约定），因为任何具有 [类别码](/latex/zh-cn/geng-duo-zhu-ti/43-table-of-tex-category-codes.md) 4 的字符

尽管每个 $$\langle$$⁠主体行$${}\_j$$⁠$$\rangle$$ 最多可以包含 $$\mathrm{K}$$ 个单元格（由 $$\langle$$⁠前导部分⁠$$\rangle$$决定）它们可以包含 *更少* 于 $$\mathrm{K}$$ 个单元格，而且任何 $$\langle$$⁠单元格$${}\_i$$⁠$$\rangle$$ .bib 文件中插入一个 % $$\langle$$⁠主体行$${}\_j$$⁠$$\rangle$$ 都可以为空。

下面的示例演示了一个 $$\langle$$⁠前导部分⁠$$\rangle$$ 的记号值 `#&#&#&#&#\cr` 这允许每个 $$\langle$$正文行$$\rangle$$最多有 5 个单元格；不过，排版后的表格中有些行少于 5 个单元格：

```latex
一个每列 1 到 5 个单元格的 \verb|\valign| 表：

\begingroup
% \hsize 控制 \valign 的列宽（排版行的尺寸）。
\hsize=40pt
\fbox{\valign{
% 使用一个允许每列有 5 个单元格的导言
% 大多数列没有提供 5 个单元格的内容
#&#&#&#&#\cr% 每列 5 个单元格
\(\mathrm{Cell}{}_1\)\cr
\(\mathrm{Cell}{}_1\)&\(\mathrm{Cell}{}_2\)\cr
\(\mathrm{Cell}{}_1\)&\(\mathrm{Cell}{}_2\)&\(\mathrm{Cell}{}_3\)\cr
\(\mathrm{Cell}{}_1\)&\(\mathrm{Cell}{}_2\)&\(\mathrm{Cell}{}_3\)&\(\mathrm{Cell}{}_4\)\cr
\(\mathrm{Cell}{}_1\)&\(\mathrm{Cell}{}_2\)&\(\mathrm{Cell}{}_3\)&\(\mathrm{Cell}{}_4\)&\(\mathrm{Cell}{}_5\)\cr
}}
\endgroup

% 注意：由于后文解释的原因
% \halign 必须放入 \vbox 中
一个每行 1 到 5 个单元格的 \verb|\halign| 表：

\fbox{%
\vbox{\halign{
% 使用一个允许每行有 5 个单元格的导言
% 大多数行没有提供 5 个单元格的内容
#&#&#&#&#\cr % 每行 5 个单元格
\(\mathrm{Cell}{}_1\)\cr
\(\mathrm{Cell}{}_1\)&\(\mathrm{Cell}{}_2\)\cr
\(\mathrm{Cell}{}_1\)&\(\mathrm{Cell}{}_2\)&\(\mathrm{Cell}{}_3\)\cr
\(\mathrm{Cell}{}_1\)&\(\mathrm{Cell}{}_2\)&\(\mathrm{Cell}{}_3\)&\(\mathrm{Cell}{}_4\)\cr
\(\mathrm{Cell}{}_1\)&\(\mathrm{Cell}{}_2\)&\(\mathrm{Cell}{}_3\)&\(\mathrm{Cell}{}_4\)&\(\mathrm{Cell}{}_5\)\cr
}}}
```

[在 Overleaf 中打开此示例](/latex/zh-cn/shen-du-wen-zhang/15-how-do-tex-engines-typeset-tables-2.md)

此示例生成如下输出：

![](/files/2a48539346b30909c31f076007b7ae010bcee2f8)

接下来的 `\halign` 示例展示了每行单元格数量可变，以及单元格可以为空的能力——注意空单元格是如何由连续的 **`&`** 表格中的字符产生的：

```latex
一个含有一些空单元格的 \verb|\halign| 表——注意表格 \(\langle\texttt{body}\rangle\) 中有连续的 \texttt{\&} 字符：

\fbox{%
\vbox{\halign{
% 使用一个允许每行有 5 个单元格的导言
% 大多数行没有提供 5 个单元格的内容
#&#&#&#&#\cr % 每行 5 个单元格
\(\mathrm{Cell}{}_1\)\cr
\(\mathrm{Cell}{}_1\)&\(\mathrm{Cell}{}_2\)\cr
\(\mathrm{Cell}{}_1\)&&\(\mathrm{Cell}{}_3\)\cr
&\(\mathrm{Cell}{}_2\)&\(\mathrm{Cell}{}_3\)&\(\mathrm{Cell}{}_4\)\cr
\(\mathrm{Cell}{}_1\)&\(\mathrm{Cell}{}_2\)&&&\(\mathrm{Cell}{}_5\)\cr
}}}
```

[在 Overleaf 中打开此示例](https://www.overleaf.com/docs?engine=pdflatex\&snip_name=Empty+cells+Number+of+cells+per+row\&snip=%5Cdocumentclass%7Barticle%7D%0A%5Cusepackage%7Bparskip%7D+%25+Set+%5Cparindent+to+0pt%0A%25+Choose+a+conveniently+small+page+size%0A%5Cusepackage%5Bpaperheight%3D16cm%2Cpaperwidth%3D12cm%2Ctextwidth%3D8cm%5D%7Bgeometry%7D%0A%25+Space+out+the+%5Chalign+columns+and+%5Cvalign+rows%0A%5Csetlength%7B%5Ctabskip%7D%7B8pt%7D+%0A%25+Close-fitting+box+borders+%0A%5Csetlength%7B%5Cfboxsep%7D%7B0pt%7D%0A%5Cbegin%7Bdocument%7D%0AAn+%5Cverb%7C%5Chalign%7C+table+with+some+empty+cells---note+there+are+consecutive+%5Ctexttt%7B%5C%26%7D+characters+in+the+table+%5C%28%5Clangle%5Ctexttt%7Bbody%7D%5Crangle%5C%29%3A%0A%0A%5Cfbox%7B%25%0A%5Cvbox%7B%5Chalign%7B%0A%25+Use+a+preamble+that+allows+for+5+cells+per+row%0A%25+Most+rows+don%27t+provide+content+for+5+cells%0A%23%26%23%26%23%26%23%26%23%5Ccr+%25+5+cells+per+row%0A%5C%28%5Cmathrm%7BCell%7D%7B%7D_1%5C%29%5Ccr+%0A%5C%28%5Cmathrm%7BCell%7D%7B%7D_1%5C%29%26%5C%28%5Cmathrm%7BCell%7D%7B%7D_2%5C%29%5Ccr%0A%5C%28%5Cmathrm%7BCell%7D%7B%7D_1%5C%29%26%26%5C%28%5Cmathrm%7BCell%7D%7B%7D_3%5C%29%5Ccr%0A%26%5C%28%5Cmathrm%7BCell%7D%7B%7D_2%5C%29%26%5C%28%5Cmathrm%7BCell%7D%7B%7D_3%5C%29%26%5C%28%5Cmathrm%7BCell%7D%7B%7D_4%5C%29%5Ccr%0A%5C%28%5Cmathrm%7BCell%7D%7B%7D_1%5C%29%26%5C%28%5Cmathrm%7BCell%7D%7B%7D_2%5C%29%26%26%26%5C%28%5Cmathrm%7BCell%7D%7B%7D_5%5C%29%5Ccr%0A%7D%7D%7D%0A%5Cend%7Bdocument%7D)

此示例生成如下输出：

![](/files/420cbc549d5e7b23f570564e56198d056ff9da75)

### 在表格排版中，& 和 # 没有什么特殊之处

TeX 对这些字符的使用 `&` 和 `#` 在……的排版中 `\halign`- 或 `\valign`基于……的表格是一种传统，源自 Knuth 最初的 plain TeX 宏。完全可以使用除 `&` 和 `#` 之外的字符，只需为你偏好的替代字符分配适当的类别码，如下例所示：

* 将其替换为 `&` 与 `@` 通过将 `@` 分配到类别码 4
* 将其替换为 `#` 与 `|` 通过将 `|` 分配到类别码 6（用于宏参数）

通过使用 `\begingroup` 和 `\endgroup`:

```latex
\documentclass{article}
\begin{document}
\begingroup
\catcode`@=4
\catcode`|=6
\halign{
|@|@|\cr
A@B@C\cr
D@E@F\cr
}
\endgroup
\end{document}
```

[在 Overleaf 中打开此示例](https://www.overleaf.com/docs?engine=pdflatex\&snip_name=Tables+and+category+codes\&snip=%5Cdocumentclass%7Barticle%7D%0A%5Cbegin%7Bdocument%7D%0A%5Cbegingroup%0A%5Ccatcode%60%40%3D4%0A%5Ccatcode%60%7C%3D6%0A%5Chalign%7B%0A%7C%40%7C%40%7C%5Ccr%0AA%40B%40C%5Ccr%0AD%40E%40F%5Ccr%0A%7D%0A%5Cendgroup%0A%5Cend%7Bdocument%7D)

## 重新引入 \noalign 命令

TeX 引擎提供内置（原始） `\noalign` 命令：

`\noalign{`$$\langle$$⁠`记号`⁠$$\rangle$$`}`

其中 $$\langle$$⁠`记号`⁠$$\rangle$$ 是字符和/或 TeX/LaTeX 命令。 `\noalign` 命令仅可用于 `\halign` 或 `\valign` 表格中：在这些之外使用会产生错误。

……的用途是 `\noalign` 是允许“插入”文本和 TeX/LaTeX 命令 *在……之间* ……的行之间 `\halign` 表格，或……的列之间 `\valign` ……最常见的用途是 `\noalign` 是创建表格线（规则线）：

* *水平* ……之间的线 `\halign` 表格行
* *垂直* ……之间的线 `\valign` 表格列

请注意以下几点：

* 该 `\noalign` 命令是 ***不以\*\*\*\*结束\*\*\*\* ****`\cr`**** \*\*\*\*\*\*\*\*命令***
* 在……中允许的命令集合 `\noalign{...}` 取决于它是否用于 $$\langle$$⁠`主体`⁠$$\rangle$$ 一个……的 `\halign` 或 `\valign` 表格（即在垂直或水平模式中）。

现在我们可以说，表格 $$\langle$$⁠`主体`⁠$$\rangle$$ 的记号值 `\halign` 或 `\valign` 可以由单独的行组成 $$\langle$$⁠主体行$${}\_i$$⁠$$\rangle$$`\cr` 穿插着 `\noalign` 命令；众多可能性/组合之一可能是：

`\noalign{`$$\langle$$⁠`记号`⁠$$\rangle$$`}` $$\langle$$⁠主体行$${}\_1$$⁠$$\rangle$$\cr $$\langle$$⁠主体行$${}\_2$$⁠$$\rangle$$\cr `\noalign{`$$\langle$$⁠`更多标记`⁠$$\rangle$$`}` $$\langle$$⁠主体行$${}*3$$⁠$$\rangle$$\cr ... $$\langle$$⁠主体行$${}*\mathrm{N}$$⁠$$\rangle$$\cr `\noalign{`$$\langle$$⁠`其他标记`⁠$$\rangle$$`}`

### 使用 \noalign 的示例

我们会在本系列文章的后面部分查看其他用例，但这里先给出一个基本示例，演示如何通过 `\noalign`:

```latex
\setlength{\tabskip}{5pt}

使用 \verb|\noalign| 在 \verb|\halign| 表的各行之间放置水平线：
\vspace{6pt}

\halign{%
#&#&#&#&#\cr
\noalign{\hrule\kern2pt}
1&2&3&4&5\cr
\noalign{\kern2pt\hrule\kern2pt}
6&7&8&9&10\cr
\noalign{\kern2pt\hrule}
}

使用 \verb|\noalign| 在 \verb|\valign| 表的各列之间放置垂直线：
\vspace{6pt}

\begingroup % 将 \parindent 和 \hsize 的更改保持在局部
\parindent=0pt
\hsize=50pt
\valign{%
#&#&#&#&#\cr
\noalign{\vrule\kern2pt}
1&2&3&4&5\cr
\noalign{\kern2pt\vrule\kern2pt}
6&7&8&9&10\cr
\noalign{\kern2pt\vrule}
}
\endgroup
```

[在 Overleaf 中打开此示例](https://www.overleaf.com/docs?engine=pdflatex\&snip_name=Example+of+the+noalign+command\&snip=%5Cdocumentclass%7Barticle%7D%0A%5Cusepackage%5Bpaperheight%3D16cm%2Cpaperwidth%3D10cm%2Ctextwidth%3D6cm%5D%7Bgeometry%7D%0A%5Cusepackage%7Bverbatim%7D+%0A%5Cusepackage%7Bparskip%7D%0A%5Cbegin%7Bdocument%7D%0A%5Cpagestyle%7Bempty%7D%0A%5Csetlength%7B%5Ctabskip%7D%7B5pt%7D%0A%0AUsing+%5Cverb%7C%5Cnoalign%7C+to+place+horizontal+rules+between+rows+of+an+%5Cverb%7C%5Chalign%7C+table%3A%0A%5Cvspace%7B6pt%7D%0A%0A%5Chalign%7B%25%0A%23%26%23%26%23%26%23%26%23%5Ccr%0A%5Cnoalign%7B%5Chrule%5Ckern2pt%7D%0A1%262%263%264%265%5Ccr%0A%5Cnoalign%7B%5Ckern2pt%5Chrule%5Ckern2pt%7D%0A6%267%268%269%2610%5Ccr%0A%5Cnoalign%7B%5Ckern2pt%5Chrule%7D%0A%7D%0A%0AUsing+%5Cverb%7C%5Cnoalign%7C+to+place+vertical+rules+between+columns+of+a+%5Cverb%7C%5Cvalign%7C+table%3A%0A%5Cvspace%7B6pt%7D%0A%0A%5Cbegingroup+%25+keep+changes+to+%5Cparindent+and+%5Chsize+local%0A%5Cparindent%3D0pt%0A%5Chsize%3D50pt%0A%5Cvalign%7B%25%0A%23%26%23%26%23%26%23%26%23%5Ccr%0A%5Cnoalign%7B%5Cvrule%5Ckern2pt%7D%0A1%262%263%264%265%5Ccr%0A%5Cnoalign%7B%5Ckern2pt%5Cvrule%5Ckern2pt%7D%0A6%267%268%269%2610%5Ccr%0A%5Cnoalign%7B%5Ckern2pt%5Cvrule%7D%0A%7D%0A%5Cendgroup%0A%5Cend%7Bdocument%7D)

此示例生成如下输出：

![](/files/369c01d857189102740077a37d72717d8e85104a)

## 重新讨论 \tabskip

我们将更仔细地看一下 `\tabskip` 命令，在……的基础上 [前一节中的介绍](#tabskip).

该 `\tabskip` 命令设置一种特殊形式的“间距”（粘连）的值，用于 *专门* 在表格排版中：其目的是在表格行或列之间提供间距：

* 用于 `\halign` 表格： `\tabskip` 粘连会插入在表格之前和之后（即左右两侧），以及表格列之间
* 用于 `\valign` 表格： `\tabskip` 粘连会插入在表格之前和之后（即上方和下方），以及表格行之间

……的值 `\tabskip` 可以使用 LaTeX 的 `\setlength` 命令：

`\setlength{\tabskip}{`$$\langle$$⁠`粘连值`⁠$$\rangle$$`}`

其中 $$\langle$$⁠`粘连值`⁠$$\rangle$$ 可以是：

* 一个固定长度，例如 `5pt`, `3mm`，或
* 一个有限可伸缩的粘连，例如 `3pt plus 2pt minus 1pt`，或
* 一个无限可伸缩的粘连，例如 `0pt plus1fill`.

你也可以直接设置 `\tabskip` （绕过 `\setlength`）通过编写

`\tabskip`=$$\langle$$⁠`粘连值`⁠$$\rangle$$

不过，对……值的任何更改 `\tabskip` 粘连只会在以下情况下影响表格间距：

* 做出 *在* 该 `\halign` 或 `\valign` 命令被处理，或者
* 在表格内部做出 $$\langle$$⁠`导言区`⁠$$\rangle$$

尝试设置 `\tabskip` 在表格内容中（表格中的单元格内）设置……的值 $$\langle$$⁠`主体`⁠$$\rangle$$) *不会* 不会改变……的间距 `\halign` 表格列或 `\valign` 表格行。……出现这种行为的原因 `\tabskip` 可追溯到……所起的作用 $$\langle$$⁠`导言区`⁠$$\rangle$$ 在表格排版过程中——这些过程我们稍后会更详细地探讨。

### 眼见为实

为了帮助直观显示表格排版中使用的各种间距/粘连，尤其是

* `\tabskip` 胶水
* `\baselineskip` 胶水
* 手动字距调整（`\kern`)

Overleaf 准备了一个基于 LuaTeX 的项目，用于给表格的各个组成部分上色。选择 LuaTeX 是因为它能够对已排版表格的内部数据/结构进行低层重新处理，但这里我们不展开这些细节。

下面是一些示例，展示了 `\tabskip`的各种应用

### tabskip 示例 1

让我们来看看 `\tabskip` 在一个 `\halign` 和 `\valign` 表格。我们将展示实际排版的表格，并加上边框以直观显示其大小和间距，同时提供带注释的图形，其中包含着色版本，清楚展示每个表格中各种粘连/间距的大小。

首先， `\halign`:

```latex
% 为了直观显示表格的范围，我们会给它加上边框
\setlength{\fboxsep}{0pt} % 使用紧贴内容的边框

% 这里我们“直接”设置 \tabskip
\tabskip5pt % 在表格外设置初始 \tabskip 值

% 要给表格加边框，必须将其保存到一个 TeX 盒子中。
% \halign 必须放在 \vbox 中，因为 \halign 必须
% 在“垂直模式”中处理：\hbox 不行，因为
% 它是在“水平模式”中处理的

\fbox{\vbox{\halign{
\tabskip10pt#&
\tabskip15pt#&
\tabskip20pt#\cr
A&B&C\cr
D&E&F\cr
G&H&I\cr
}}}
```

[在 Overleaf 中打开此示例](https://www.overleaf.com/docs?engine=pdflatex\&snip_name=Tabskip+glue+in+an+halign\&snip=%5Cdocumentclass%7Barticle%7D%0A%5Cusepackage%5Bpaperheight%3D16cm%2Cpaperwidth%3D10cm%2Ctextwidth%3D6cm%5D%7Bgeometry%7D%0A%5Cusepackage%7Bverbatim%7D+%0A%5Cusepackage%7Bparskip%7D+%25+sets+%5Cparindent+to+0pt%0A%5Cbegin%7Bdocument%7D%0A%5Cpagestyle%7Bempty%7D%0A%25+To+visualize+the+table%27s+extent+we%27ll+put+a+border+around+it+%0A%5Csetlength%7B%5Cfboxsep%7D%7B0pt%7D+%25+Use+close-fitting+borders%0A%0A%25+Here+we+set+%5Ctabskip+%22directly%22%0A%5Ctabskip5pt+%25+Set+the+initial+%5Ctabskip+value+outside+the+table%0A%0A%25+To+put+a+border+around+the+table+it+has+to+be+saved+to+a+TeX+box.%0A%25+An+%5Chalign+has+to+be+placed+in+a+%5Cvbox+because+%5Chalign+must+be+%0A%25+processed+in+a+%22vertical+mode%22%3A+an+%5Chbox+will+not+work+because%0A%25+that+is+processed+in+a+%22horizontal+mode%22%0A%0A%5Cfbox%7B%5Cvbox%7B%5Chalign%7B%0A%5Ctabskip10pt%23%26%0A%5Ctabskip15pt%23%26%0A%5Ctabskip20pt%23%5Ccr%0AA%26B%26C%5Ccr%0AD%26E%26F%5Ccr%0AG%26H%26I%5Ccr%0A%7D%7D%7D%0A%5Cend%7Bdocument%7D)

此示例生成如下输出：

![](/files/5cd71bd2c9c85805ba7f1318f675da98b15f3953)

下一幅图是前一个示例生成的表格的更大、着色并加注释的版本：

![](/files/344d6d32175ea57f778a6759fb37306348790850)

这里有 4 处 `\tabskip` 命令，每一处对应表格中某个特定的间距位置：

1. `\tabskip5pt` 用于表格外，并设置 `\tabskip` 应用在每行第一个单元格之前（左侧）的值。
2. `\tabskip10pt` 设置在……的第一个单元格模板中 $$\langle$$⁠`导言区`⁠$$\rangle$$ 它影响……之间的间距 $$\langle$$⁠单元格$${}\_1$$⁠$$\rangle$$ 和 $$\langle$$⁠单元格$${}\_2$$⁠$$\rangle$$ 每一行的……
3. `\tabskip15pt` 设置在……的第二个单元格模板中 $$\langle$$⁠`导言区`⁠$$\rangle$$ 它影响……之间的间距 $$\langle$$⁠单元格$${}\_2$$⁠$$\rangle$$ 和 $$\langle$$⁠单元格$${}\_3$$⁠$$\rangle$$ 每一行的……
4. `\tabskip20pt` 设置在……的第三个，也是最后一个，单元格模板中 $$\langle$$⁠`导言区`⁠$$\rangle$$ 它影响在……之后添加的间距 $$\langle$$⁠单元格$${}\_3$$⁠$$\rangle$$，即每行的最后一个单元格。

接下来， `\valign`

```latex
\setlength{\fboxsep}{0pt} % 使用紧贴内容的边框
\tabskip5pt % 在表格外设置初始 \tabskip 值

% 将 \hsize 的更改保持在局部（在一个组中）
\begingroup
% \hsize 决定 \valign 的列宽
\setlength{\hsize}{50pt}
% 因为 \valign 可以放在 \vbox 或 \hbox 中，所以我们可以使用
% 直接使用 \fbox
\fbox{\valign{
\tabskip10pt#&
\tabskip15pt#&
\tabskip20pt#\cr
A&B&C\cr
E&E&F\cr
G&H&I\cr
}}
\endgroup
```

[在 Overleaf 中打开此示例](https://www.overleaf.com/docs?engine=pdflatex\&snip_name=Example+halign\&snip=%5Cdocumentclass%7Barticle%7D%0A%5Cusepackage%5Bpaperheight%3D16cm%2Cpaperwidth%3D10cm%2Ctextwidth%3D6cm%5D%7Bgeometry%7D%0A%5Cusepackage%7Bverbatim%7D+%0A%5Cusepackage%7Bparskip%7D+%25+sets+%5Cparindent+to+0pt%0A%5Cbegin%7Bdocument%7D%0A%5Cpagestyle%7Bempty%7D%0A%5Csetlength%7B%5Cfboxsep%7D%7B0pt%7D+%25+Use+close-fitting+borders%0A%5Ctabskip5pt+%25+Set+the+initial+%5Ctabskip+value+outside+the+table%0A%0A%25+Keep+changes+to+%5Chsize+local+%28in+a+group%29%0A%5Cbegingroup%0A%25+%5Chsize+determines+the+%5Cvalign+column+widths%0A%5Csetlength%7B%5Chsize%7D%7B50pt%7D+%0A%25+Because+%5Cvalign+can+be+placed+in+a+%5Cvbox+or+%5Chbox+we+can+use+%0A%25+%5Cfbox+directly%0A%5Cfbox%7B%5Cvalign%7B%0A%5Ctabskip10pt%23%26%0A%5Ctabskip15pt%23%26%0A%5Ctabskip20pt%23%5Ccr%0AA%26B%26C%5Ccr%0AE%26E%26F%5Ccr%0AG%26H%26I%5Ccr%0A%7D%7D%0A%5Cendgroup%0A%5Cend%7Bdocument%7D)

此示例生成如下输出：

![](/files/8b14c71eebeada4067e5dfe0a1ecbf7f194c6fff)

同样，下一幅图是前一个示例生成的表格的更大、着色并加注释的版本：

![](/files/62873a0913df5702d81677b9841a399760f20f87)

与……一样 `\halign` 示例一样，这里也有 4 处 `\tabskip` 命令。不过，对于 `\valign` 表格， `\tabskip` 会插入在表格行之间：

1. `\tabskip5pt` 用于表格外，并设置 `\tabskip` 应用在每列第一个单元格之前（上方）的值。
2. `\tabskip10pt` 设置在……的第一个单元格模板中 $$\langle$$⁠`导言区`⁠$$\rangle$$ 它影响……之间的间距 $$\langle$$⁠单元格$${}\_1$$⁠$$\rangle$$ 和 $$\langle$$⁠单元格$${}\_2$$⁠$$\rangle$$ 每一列的。
3. `\tabskip15pt` 设置在……的第二个单元格模板中 $$\langle$$⁠`导言区`⁠$$\rangle$$ 它影响……之间的间距 $$\langle$$⁠单元格$${}\_2$$⁠$$\rangle$$ 和 $$\langle$$⁠单元格$${}\_3$$⁠$$\rangle$$ 每一列的。
4. `\tabskip20pt` 设置在……的第三个，也是最后一个，单元格模板中 $$\langle$$⁠`导言区`⁠$$\rangle$$ 它影响在……之后添加的间距 $$\langle$$⁠单元格$${}\_3$$⁠$$\rangle$$，即每列的最后一个单元格。

**总结/结论**

* 在一个 `\halign` 表格， `\tabskip` 粘连会放在一行中每个单元格的左右两侧，从而拉开表格列之间的间距。
* 在一个 `\valign` 表格， `\tabskip` 粘连会放在一列中每个单元格的上方和下方，从而拉开表格行之间的间距。

### \tabskip 和 \noalign

#### 使用 \halign

下面的 `\halign` 示例使用 `\tabskip` 粘连，并且还演示了 `\noalign` 命令，使用它在……的各行上方和下方放置有间距的规则线 `\halign` 表格。这些线是通过 `\hrule` （原始）命令和由 `\kern`:

```latex
\setlength{\tabskip}{5pt} % 在表格外设置 \tabskip

\halign{
#&#&#&#&#\cr % <导言>
\noalign{\hrule\kern2pt} % 第 1 行之前的有间距线
1&2&3&4&5\cr % 第 1 行
\noalign{\kern2pt\hrule\kern2pt} % 第 1/2 行之间的有间距线
6&7&8&9&10\cr % 第 2 行
\noalign{\kern2pt\hrule\kern2pt} % 第 2/3 行之间的有间距线
11&12&13&14&15\cr % 第 3 行
16&17&18&19&20\cr % 第 4 行——第 3/4 行之间没有规则线
\noalign{\kern2pt\hrule} % 表格末尾的间距线
}
```

[在 Overleaf 中打开此示例](https://www.overleaf.com/docs?engine=pdflatex\&snip_name=Example+halign\&snip=%5Cdocumentclass%7Barticle%7D%0A%5Cusepackage%5Bpaperheight%3D16cm%2Cpaperwidth%3D10cm%2Ctextwidth%3D6cm%5D%7Bgeometry%7D%0A%5Cusepackage%7Bverbatim%7D+%0A%5Cusepackage%7Bparskip%7D%0A%5Cbegin%7Bdocument%7D%0A%5Cpagestyle%7Bempty%7D%0A%5Csetlength%7B%5Ctabskip%7D%7B5pt%7D+%25+Set+%5Ctabskip+outside+of+the+table%0A%0A%5Chalign%7B%0A%23%26%23%26%23%26%23%26%23%5Ccr+%25+The+%3Cpreamble%3E%0A%5Cnoalign%7B%5Chrule%5Ckern2pt%7D+%25+Spaced+rule+before+row+1%0A1%262%263%264%265%5Ccr+%25+Row+1%0A%5Cnoalign%7B%5Ckern2pt%5Chrule%5Ckern2pt%7D+%25+Spaced+rule+between+rows+1%2F2+%0A6%267%268%269%2610%5Ccr+%25+Row+2%0A%5Cnoalign%7B%5Ckern2pt%5Chrule%5Ckern2pt%7D+%25+Spaced+rule+between+rows+2%2F3+%0A11%2612%2613%2614%2615%5Ccr+%25+Row+3%0A16%2617%2618%2619%2620%5Ccr+%25+Row+4---no+rules+between+rows+3%2F4%0A%5Cnoalign%7B%5Ckern2pt%5Chrule%7D+%25+Space+rule+at+table+end%0A%7D%0A%5Cend%7Bdocument%7D)

该示例生成如下所示的表格，并进一步添加了注释，以重现 (La)TeX 代码和编号 (1) 到 (4) 来列举这些 `\noalign` 命令，其中包含规则线和 kern，同时给出其对应的排版输出：

![](/files/d5bcadc8f54f45c847f46a31597cd6239b9f9408)

下图展示了表格的着色版本，并用标注显示表格中的各种间距/粘连：

![](/files/9ce3b919d8806d775773160055c67034816253dd)

请注意以下几点：

* ……的使用 `\noalign` 在某些行之间插入规则线，以及手动使用 `\kern` 值来在规则线前后留出一些空间。TeX 引擎不会在……之后插入 `\baselineskip` 排版后的规则线后面的粘连，所以需要手动使用 `\kern` （也可以使用其他间距命令）；
* `\baselineskip` 粘连会自动插入在第 3 行和第 4 行之间。

#### 使用 \valign

下面的 `\valign` 示例使用与前一个相同的数据 `\halign`:

```latex
\begingroup
\setlength{\parindent}{10pt}
\setlength{\hsize}{50pt}
\setlength{\tabskip}{5pt}
\valign{
#&#&#&#&#\cr
\noalign{\vrule\kern2pt}
1&2&3&4&5\cr
\noalign{\kern2pt\vrule\kern2pt}
6&7&8&9&10\cr
\noalign{\kern2pt\vrule\kern2pt}
11&12&13&14&15\cr
16&17&18&19&20\cr
\noalign{\kern2pt\vrule}
}
\endgroup
```

[在 Overleaf 中打开此示例](https://www.overleaf.com/docs?engine=pdflatex\&snip_name=Example+halign\&snip=%5Cdocumentclass%7Barticle%7D%0A%5Cusepackage%5Bpaperheight%3D16cm%2Cpaperwidth%3D12cm%2Ctextwidth%3D10cm%5D%7Bgeometry%7D%0A%5Cbegin%7Bdocument%7D%0A%5Cpagestyle%7Bempty%7D%0A%5Cbegingroup%0A%5Csetlength%7B%5Cparindent%7D%7B10pt%7D%0A%5Csetlength%7B%5Chsize%7D%7B50pt%7D%0A%5Csetlength%7B%5Ctabskip%7D%7B5pt%7D%0A%5Cvalign%7B%0A%23%26%23%26%23%26%23%26%23%5Ccr%0A%5Cnoalign%7B%5Cvrule%5Ckern2pt%7D%0A1%262%263%264%265%5Ccr%0A%5Cnoalign%7B%5Ckern2pt%5Cvrule%5Ckern2pt%7D%0A6%267%268%269%2610%5Ccr%0A%5Cnoalign%7B%5Ckern2pt%5Cvrule%5Ckern2pt%7D%0A11%2612%2613%2614%2615%5Ccr%0A16%2617%2618%2619%2620%5Ccr%0A%5Cnoalign%7B%5Ckern2pt%5Cvrule%7D%0A%7D%0A%5Cendgroup%0A%5Cend%7Bdocument%7D)

该示例生成如下所示的表格，并进一步添加了注释，以重现 (La)TeX 代码和编号 (1) 到 (4) 来列举这些 `\noalign` 命令，其中包含规则线和 kern，同时给出其对应的排版输出：

![](/files/e9a31a6b39606c92664e728b549184c5f2102575)

![](/files/1da6261c99a67a3e67f2d0523d76b3cd351f7477)

### 一个带文本行的 \valign 表

下一个示例

```latex
\setlength{\tabskip}{5pt}
\begingroup % 将 \parindent 和 \hsize 的更改保持在局部
\setlength{\parindent}{10pt}
\setlength{\hsize}{75pt}
\valign{
#&#&#\cr
\noalign{\vrule\kern5pt}
TeX{} 可以排版非常复杂的
表格。&这里还有一点额外的
文本。&最后，再加上一行额外的
位于这一列中。\cr
\noalign{\kern5pt\vrule\kern5pt}
A&B&C\cr
\noalign{\kern5pt\vrule\kern5pt}
D&E&F\cr
G&H&I\cr
\noalign{\kern5pt\vrule}
}
\endgroup
```

[在 Overleaf 中打开此示例](https://www.overleaf.com/docs?engine=pdflatex\&snip_name=Example+valign+command\&snip=%5Cdocumentclass%7Barticle%7D%0A%5Cusepackage%5Bpaperheight%3D16cm%2Cpaperwidth%3D16cm%2Ctextwidth%3D12cm%5D%7Bgeometry%7D%0A%5Cbegin%7Bdocument%7D%0A%5Csetlength%7B%5Ctabskip%7D%7B5pt%7D%0A%5Cbegingroup+%25+Keep+changes+to+%5Cparindent+and+%5Chsize+local%0A%5Csetlength%7B%5Cparindent%7D%7B10pt%7D%0A%5Csetlength%7B%5Chsize%7D%7B75pt%7D%0A%5Cvalign%7B%0A%23%26%23%26%23%5Ccr%0A%5Cnoalign%7B%5Cvrule%5Ckern5pt%7D%0A%5CTeX%7B%7D+can+typeset+very+complex%0Atables.%26Here%27s+a+bit+of+extra+%0Atext.%26And%2C+finally%2C+an+extra+line%0Ain+this+column.%5Ccr%0A%5Cnoalign%7B%5Ckern5pt%5Cvrule%5Ckern5pt%7D%0AA%26B%26C%5Ccr%0A%5Cnoalign%7B%5Ckern5pt%5Cvrule%5Ckern5pt%7D%0AD%26E%26F%5Ccr%0AG%26H%26I%5Ccr%0A%5Cnoalign%7B%5Ckern5pt%5Cvrule%7D%0A%7D%0A%5Cendgroup%0A%5Cend%7Bdocument%7D)

此示例生成如下输出：

## 设置行宽和列高

## 更多关于表格的内容 $$\langle$$⁠前导部分⁠$$\rangle$$


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://ayakaleaf-pro.ayaka.space/latex/zh-cn/shen-du-wen-zhang/15-how-do-tex-engines-typeset-tables-2.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
