@AlexeyMalistov 回答了让 LaTeX 在表格中的每一行之间绘制一个 \hline 而不使用 \hline?在 TeX.SE 出现之前,StackOverflow 上就有这个问题。后来 TeX.SE 上也出现了同样的问题:带有自动 \hline 的表格。
Malistov 的答案成功地在表格的每一行之间生成了一条线,是在之前添加以下内容tabular
:
\catcode`@=11
\let \savecr \@tabularcr
\def\@tabularcr{\savecr\hline}
\catcode`@=12
我认为这重新定义了制表环境中的换行符,因此插入\hline
了,但代码对我来说仍然只是巫术。有人愿意解释一下它是如何工作的吗?谢谢。
答案1
破解密码
\catcode`@=11
\let \savecr \@tabularcr
\def\@tabularcr{\savecr\hline}
\catcode`@=12
逐步向下:
\catcode`@=11
这会将 的类别代码更改为
@
“字母”,因为@
否则可能无法在宏名称中使用。您会注意到,后续行使用\@tabularcr
,我们需要@
将其类型设为“字母”。其他人喜欢使用\makeatletter
(请参阅做什么\makeatletter
和\makeatother
做什么?)。\let \savecr \@tabularcr
这将立即复制一份
\@tabularcr
并将其存储在 中\savecr
。这样您就可以修改\@tabularcr
(后续行)但仍保留旧版本的副本。\def\@tabularcr{\savecr\hline}
这里
\@tabularcr
实际上被重新定义为\savecr
(上面存储为\@tabularcr
前这个重新定义后面跟着\hline
- 你想要的水平规则。为什么要(重新)定义\@tabularcr
?从 LaTeX 内核(latex.ltx
),环境的定义tabular
执行(在稍后的阶段)\def\@tabular{\leavevmode \hbox \bgroup $\let\@acol\@tabacol \let\@classz\@tabclassz \let\@classiv\@tabclassiv \let\\\@tabularcr\@tabarray}
在这里您可以看到(在最后一行),在开始实际之前将其
\\
设置为等同于,因此将具有现在包括附加的新定义。\@tabularcr
tabular
\\
\@tabularcr
\hline
\catcode`@=12
这会将 的类别代码恢复
@
为 其他。有些用户更喜欢使用\makeatother
。
有关类别代码的参考,请参阅类别代码是什么?
当然,在 a 之前添加此内容tabular
会使它在您的文档中全局化。也许更明智的做法是将其包含在一个组中(或作为环境)以本地化更改。或者,您可以定义命令开关来“激活”此\hline
自动化并在稍后“停用”它。
答案2
该代码似乎可以工作,但实际上不行。我们来看一个例子:
\documentclass{article}
\catcode`@=11
\let \savecr \@tabularcr
\def\@tabularcr{\savecr\hline}
\catcode`@=12
\begin{document}
\begin{tabular}{c}
a\\[1cm]
b
\end{tabular}
\end{document}
输出
让我们看看为什么。的原始定义\@tabularcr
是
% latex.ltx, line 5040:
\def\@tabularcr{%
{\ifnum0=`}\fi\@ifstar\@xtabularcr\@xtabularcr}
并且已经注意到一些事情:如果由于错误或因为tabular
和之间共享了一些代码,用于结束一行的longtable
类型将不会被重新定义的命令识别和删除,因为之后的标记始终是。\\*
*
\savecr
\hline
\@tabularcr
因此输入流中的新叶子
\@xtabularcr\hline
事情又出错了,因为的定义\@xtabularcr
是
% latex.ltx, line 5042:
\def\@xtabularcr{\@ifnextchar[\@argtabularcr{\ifnum0=`{\fi}\cr}}
旁边的标记\@xtabularcr
将绝不是[
,这就是导致我的示例输出不佳的原因。
在每一行后自动添加规则的最佳方法是什么?没有,至少有两个原因:
- 每行之后不需要水平线。
- 您无法
\cline
在需要的地方添加它。
答案3
将此解决方案与 longtable 一起使用会导致一些行线丢失(如 egreg 所解释的那样)。一种解决方案是将 longtable 的块大小设置为大于表的行数:
\setcounter{LTchunksize}{1000}
注意:使用 pander 生成 RMarkdown 表时会发生这种情况:
pander(df, keep.line.breaks = TRUE, use.hyphening = TRUE, split.table = Inf)