\chapter{表格}

\ConTeXt\ 提供了多种表格形式，我们不需要全都学会，可以先学会最为简单的形式 Tabulate，等到将它用到山穷水尽也无法表达你想要的表格时，再考虑其他形式是否够用。简单的未必不好，强大的未必更好，既简单又符合自己需求的，永远都是最好的。

\section{基本用法}

首先，构造一个 2 行 3 列的表格，第 1 行的内容是 \type{1 2 3}，第二行的内容是 \type{4 5 6}，排版代码和结果如下：

\startsample
\starttabulate
\NC 1 \NC 2 \NC 3\NC\NR
\NC 4 \NC 5 \NC 6\NC\NR
\stoptabulate
\stopsample
\simplesample[option=TEX]{\null}
\getsample

\noindent 结果第 3 列跑到版面最右侧了。这是因为我们尚未定义表格各列的对齐方式。对齐方式不外乎三种，左、中、右，Tabulate 分别使用缩写 \type{l}，\type{c} 和 \type{r} 指代它们。例如，若令表格第 1 列居左，第 2 列居中，第 3 列居右，只需

\startsample
\starttabulate[|l|c|r|]
\NC 1 \NC 2 \NC 3\NC\NR
\NC 4 \NC 5 \NC 6\NC\NR
\stoptabulate
\stopsample
\simplesample[option=TEX]{\getsample}
\noindent 现在看上去像表格了，但是由于表格尚无边框线，无法看出表格各列内容的对齐状态。

想必你已经猜测出了，\type{\NC} 用于在表格的某一行构造一个单元格，上述示例中，表格内容的每一行最后一个 \type{\NC} 实际上是多余的，\ConTeXt\ 会忽略它，但是你可以将它理解为表格的单元格的边界。\type{\NR} 用于构造一个新行，即下一行。上述示例里，表格只有两行，实际上第 2 个 \type{\NR} 也是多余的，只是为了形式上更整齐而保留，\ConTeXt\ 会忽略它，你可以将它理解为表格一行的结束。

现在，将 \type{\NC} 替换为 \type{\VL}，便可画出单元格的左右边界线，即

\startsample
\starttabulate[|l|c|r|]
\VL 1 \VL 2 \VL 3\VL\NR
\VL 4 \VL 5 \VL 6\VL\NR
\stoptabulate
\stopsample
\simplesample[option=TEX]{\getsample}

\noindent 在表格每一行的开始放上 \type{\HL}，可画出表格各行横线，即

\startsample
\starttabulate[|l|c|r|]
\HL
\VL 1 \VL 2 \VL 3\VL\NR
\HL
\VL 4 \VL 5 \VL 6\VL\NR
\HL
\stoptabulate
\stopsample
\simplesample[option=TEX]{\getsample}

\noindent 可能你已经发现了，表格的竖线将被横线截断了。不必担心是你的问题，而是 Tabulate 主要用于排版横线表，例如图 \in[three-line table] 所示的在科技论文中常用的三线表。

\placefigure[force][three-line table]{三线表}{\externalfigure[09/three-line-table.pdf]}

让表格的横线和竖线完全相交并不困难，只需将单元格之间的纵向间距参数 \type{distance} 设为 \type{0pt} 或 \type{none}：

\startsample
\starttabulate[|l|c|r|][distance=none]
\HL
\VL 1 \VL 2 \VL 3\VL\NR
\HL
\VL 4 \VL 5 \VL 6\VL\NR
\HL
\stoptabulate
\stopsample
\simplesample[option=TEX]{\getsample}

\section{间距调整}

若希望单元格的宽度更宽一些，需要在列格式中设定 \type{w} 参数，例如令单元格宽度为 1 cm，只需 \type{w(1cm)} 即可。例如

\startsample
\starttabulate[|lw(1cm)|cw(1cm)|rw(1cm)|][distance=none]
\HL
\VL 1 \VL 2 \VL 3\VL\NR
\HL
\VL 4 \VL 5 \VL 6\VL\NR
\HL
\stoptabulate
\stopsample
\simplesample[option=TEX]{\getsample}

若希望文档中所有表格实例的 \type{distance} 参数皆为 \type{none}，可用 \type{\setuptabulate} 进行设定：

\starttyping[option=TEX]
\setuptabulate[distance=none]
\stoptyping

若想加大单元格的竖向间距，可用 \type{\TB} 命令插入空行予以调整。例如插入 2mm 高的空格，

\startsample
\starttabulate[|lw(1cm)|cw(1cm)|rw(1cm)|][distance=none]
\HL
\VL 1 \VL 2 \VL 3\VL\NR
\HL
\TB[2mm]
\HL
\VL 4 \VL 5 \VL 6\VL\NR
\HL
\stoptabulate
\stopsample
\simplesample[option=TEX]{\getsample}

\noindent \type{\TB} 也可以使用相对尺寸，例如 \type{2*line}，\type{line}，\type{halfline} 和 \type{quarterline} 分别为一行文字的高度的 2 倍，1 倍，1/2 倍和 1/4 倍。

由于插图不过是个头较大的文字，因此基于表格理应能实现 \in[figure-matrix] 节所述的排版插图阵列。的确可以如此，例如

\starttyping[option=TEX]
\def\figA{\externalfigure[ctxnotes.png][height=3cm]}
\def\figB{\externalfigure[ctxnotes-2.png][height=3cm]}
\placefigure{}{
  \starttabulate[|cw(6cm)|cw(6cm)|]
  \NC \figA \NC \figB \NC\NR
  \NC a \NC b\NC\NR
  \stoptabulate
}
\stoptyping
\midaligned{\externalfigure[09/01.pdf]}

\section{\type{\placetable}}

类似于插图，表格也有一个放置命令 \type{\placetable}，其用法与 \type{\placefigure} 相似。例如

\starttyping[option=TEX]
\placetable[here][表格示例]{简单的表格}{
  \starttabulate[|cw(2cm)|cw(2cm)|cw(2cm)|][distance=none]
  \HL
  \VL 1 \VL 2 \VL 3\VL\NR
  \HL
  \VL 4 \VL 5 \VL 6\VL\NR
  \HL
  \stoptabulate
}
\stoptyping
\midaligned{\externalfigure[09/02.pdf]}

对于中文排版，表格的标题，默认的设置并不符合我们的习惯，需要作一些定制。首先，将表格编号前缀设定为

\starttyping[option=TEX,space=on]
\setuplabeltext[en][table={表 }]
\stoptyping

\noindent 然后，将表格标题编号设为正体，字号比正文字号小一级，放置于表格上方，并居中对齐：

\starttyping[option=TEX]
\setupcaption
  [table]
  [headstyle=\tf,style=\tfx,location=top,align=center]
\stoptyping
\blank[line]
\midaligned{\externalfigure[09/03.pdf]}

\section{不传之秘}

在绘制表格的横线和竖线时，线条粗度可通过参数 \type{rulethickness} 进行设定。例如，将线条粗度设为 2 pt：

\startsample
\starttabulate[|c|c|c|c|c|][rulethickness=2pt]
\HL
\NC 一 \NC 二 \NC 三 \NC 四 \NC 五 \NC\NR
\HL
\NC one \NC two \NC three \NC four \NC five \NC\NR
\NC 1 \NC 2 \NC 3 \NC 4 \NC 5 \NC\NR
\HL
\stoptabulate
\stopsample
\simplesample[option=TEX]{\externalfigure[09/04.pdf]}

\noindent 但是，如果我们只想让表格的顶线和底线是粗度 2 pt，中间那条横线让它是 Tabulate 的默认粗度，该如何实现呢？

对于该问题，也许你翻遍 \ConTeXt\ 的 Wiki 或手册，都找不到答案，因为答案在 \ConTeXt\ 的 tabl-tbl.mkxl 文件里。使用以下命令可搜索该文件：

\starttyping
$ mtxrun --script base --search tabl-tbl.mkxl
\stoptyping

\noindent 需要注意的是，该文件中关于 \type{\TL}，\type{\LL} 和 \type{\BL} 的注释应该是错的。要解决上述问题，需要先了解以下细节：

\startitemize[packed]
\item 表格线粗度默认大概是 0.4 pt；
\item 横线 \type{\HL} 有着细致的类别划分，从表格的顶线到底线，依次为顶线 \type{\TL}，第一条横线 \type{\FL}，中间的横线 \type{\ML}，最后一条横线 \type{LL}，底线 \type{\BL}；
\item 若要设定表格横线的不同粗度，则横线必须按照类别使用，不可使用 \type{\HL}；
\item \type{\HL}\footnote{包括 \type{\TL}，\type{\FL}，……，\type{\BL}。}和 \type{\VL} 可以接受两个参数，一个是表格线既定粗度的倍数，另一个是表格线颜色。
\stopitemize

\noindent 然后，将上述示例修改为

\starttyping[option=TEX]
\starttabulate[|c|c|c|c|c|][rulethickness=2pt]
\TL
\NC 一 \NC 二 \NC 三 \NC 四 \NC 五 \NC\NR
\FL
\NC one \NC two \NC three \NC four \NC five \NC\NR
\NC 1 \NC 2 \NC 3 \NC 4 \NC 5 \NC\NR
\BL
\stoptabulate
\stoptyping

\noindent 由于该表格内容只有三行，因此只有顶线，第一条横线和底线，亦即无中间横线和最后一条横线。为了更加充分演示问题是如何解决的，可以让该表格的内容再丰富一些：

\starttyping[option=TEX]
\starttabulate[|c|c|c|c|c|][rulethickness=2pt]
\TL
\NC 一 \NC 二 \NC 三 \NC 四 \NC 五 \NC\NR
\FL
\NC 甲 \NC 乙 \NC 丙 \NC 丁 \NC 戊 \NC\NR
\ML
\NC one \NC two \NC three \NC four \NC five \NC\NR
\LL
\NC 1 \NC 2 \NC 3 \NC 4 \NC 5 \NC\NR
\BL
\stoptabulate
\stoptyping

现在要保持 \type{\TL} 和 \type{\BL} 为既定粗度 2 pt，将 \type{\FL}，\type{\ML} 和 \type{\LL} 的粗度设置为 0.2 倍的既定粗度，及 0.4 pt，顺便试验一下颜色是否真的可用，见示例 \in[HL example] 对应的代码，结果只有 \type{\ML} 变成了双线，其他皆符合预期。

为何 \type{\ML} 如此不配合呢？我猜也许它本来就是在绘制双线，因为 Tabulate 支持表格分页断开，即一个表格若处于页面底部且不能完全被当前页面容纳时，\ConTeXt\ 可将其断开，一部分在当前页面，另一部分在下一页面。为了让断开后的表格完整，\type{\ML} 必须是双线。若将示例 \in[HL example] 中的 \type{\ML} 换成 \type{\HL}，结果同样是双线。若不需要双线，可将 \type{\ML} 皆换为 \type{\FL} 或 \type{\LL}。

为了避免上述莫名其妙的问题，若只是令表格顶线和底线变粗，不必设定 \type{rulethickness} 参数，而是修改顶线和底线的粗度，令其他表格线的粗度皆为默认值。

\startsample
\starttabulate[|c|c|c|c|c|][rulethickness=2pt]
\TL
\NC 一 \NC 二 \NC 三 \NC 四 \NC 五 \NC\NR
\FL[0.2,red]
\NC 甲 \NC 乙 \NC 丙 \NC 丁 \NC 戊 \NC\NR
\ML[0.2,blue]
\NC one \NC two \NC three \NC four \NC five \NC\NR
\LL[0.2,magenta]
\NC 1 \NC 2 \NC 3 \NC 4 \NC 5 \NC\NR
\BL
\stoptabulate
\stopsample
\sample[option=TEX][HL example]{修改表格线粗度和颜色}{\getsample}

\section{小结}

除了在设定表格线粗度时不尽人意之外，Tabulate 堪当日常之用。它还有一些功能，本章尚未涉及，诸如跨栏，分页，段落等，这部分功能在后续章节介绍其他排版元素时，将作为搭配示例予以介绍。

待到 Tabulate 用至捉襟见肘之时，可使用「终极表格」，其文档在你的 \ConTeXt\ 环境里，可通过以下命令搜索：

\starttyping
$ mtxrun --script base --search xtables-mkiv.pdf
\stoptyping
