> For the complete documentation index, see [llms.txt](https://overleaf-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://overleaf-pro.ayaka.space/latex/zh-cn/shen-ru-wen-zhang/15-how-do-tex-engines-typeset-tables-2.md).

# TeX 引擎如何排版表格 2

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

## TeX 引擎将表格称为对齐

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

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

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

在本系列文章中，我们将探讨这两个命令，首先对其格式/结构作一个更正式的概览，为后续内容打下基础， `\halign` 和 `\valign` 以便为本系列后续的深入文章奠定基础。

### 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**{...}`：向 `\halign` 表格的自然宽度增加 30pt。相反，写作 **spread -30pt** 则会将表格宽度减少 30pt。
* `\valign **spread 20pt**{...}`：向 `\valign` 表格的自然高度增加 20pt。相反，写作 **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$$ 的一个记号值 **`到 50pt`**:

```latex
\documentclass{article}
\setlength{\fboxsep}{0pt}
\setlength{\parindent}{0pt}
\newcommand{\optspec}{\(\langle \texttt{可选规格} \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$$某个……中的第 th 个单元格 $$\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$$ 在 $$\langle$$⁠主体行$${}\_j$$⁠$$\rangle$$ 都可以为空。

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

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

\begingroup
% \hsize 控制 \valign 的列宽（排版行的大小）。
\hsize=40pt
\fbox{\valign{
% 使用一个允许每列有 5 个单元格的导言
% 大多数列没有提供 5 个单元格的内容
#&#&#&#&#\cr% 5 cells per column
\(\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 中
一个 \verb|\halign| 表，每行含 1 到 5 个单元格：

\fbox{%
\vbox{\halign{
% 使用一个允许每行有 5 个单元格的导言
% 大多数行没有提供 5 个单元格的内容
#&#&#&#&#\cr % 5 cells per row
\(\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-ru-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 cells per row
\(\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` 命令设置一种特殊形式的“间距”（glue）的值，该间距用于 *仅* 在表格排版中：其目的是在表格行或列之间提供间距：

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

……的值 `\tabskip` 可以使用 LaTeX 的……设置 `\setlength` 命令设置为特定值：

`\setlength{\tabskip}{`$$\langle$$⁠`glue 值`⁠$$\rangle$$`}`

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

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

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

`\tabskip`=$$\langle$$⁠`glue 值`⁠$$\rangle$$

但是，对……值所做的任何更改 `\tabskip` glue 只有在该更改满足以下条件时才会影响表格间距：

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

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

### 眼见为实

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

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

Overleaf 准备了一个基于 LuaTeX 的项目来为表格组件着色。选择 LuaTeX 是因为它能够对排版后表格的内部数据/结构进行底层重新处理，但这里我们不探讨这些细节。

以下是一些示例，展示了……的各种应用 `\tabskip`。对于每个示例，我们将展示实际输出以及 LuaTeX 生成的着色版本。

### \tabskip 示例 1

让我们来看看……的用法 `\tabskip` 在一个 `\halign` 和 `\valign` 表格。我们将展示实际排版的表格，并用边框可视化其大小和间距，同时给出带注释的图形，其中包含着色版本，清楚显示每个表格中各种 glue/间距的大小。

首先， `\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` glue 放在一行中每个单元格的左侧和右侧，从而拉开表格列之间的间距。
* 在一个 `\valign` 表格， `\tabskip` glue 放在一列中每个单元格的上方和下方，从而拉开表格行之间的间距。

### \tabskip 和 \noalign

#### 使用 \halign

下面的 `\halign` 示例使用 `\tabskip` glue，并且还演示了 `\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)

下图显示了该表格的着色版本，并加上标签以展示表格中的各种间距/glue：

![](/files/9ce3b919d8806d775773160055c67034816253dd)

请注意以下几点：

* ……的使用 `\noalign` 在某些行之间插入横线，以及手动使用 `\kern` 值来在横线前后留出一些空间。TeX 引擎不会在排版出的横线之后插入 `\baselineskip` glue，因此空间是通过手动使用 `\kern` （也可以使用其他间距命令）；
* `\baselineskip` glue 已自动插入在第 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://overleaf-pro.ayaka.space/latex/zh-cn/shen-ru-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.
