我有以下代码以及为表格创建行的命令:
\documentclass[letterpaper,10pt]{article}
\usepackage[utf8]{inputenc}
\usepackage{xstring}
\newcommand*{\condrow}[2]{
\IfEqCase{#1}{
{l}{#2 & & \\}
{r}{ & & #2 \\}
{c}{ & #2 & \\}
{m}{\multicolumn{3}{c}{#2} \\}
}[\PackageError{condrow}{Undefined option: #1}{}]
}
\begin{document}
\begin{tabular}{|c|c|c|}
\condrow{l}{left}
\condrow{r}{right}
\condrow{c}{center}
\multicolumn{3}{c}{manual multi} \\ % WORKS
\condrow{m}{condrow multi} % FAILS
\end{tabular}
\end{document}
\multicolumn
虽然在表格中直接使用可以工作,但\multicolumn
通过命令使用\condrow
会失败。我猜想 会\IfEqCase
在\condrow
命令开头添加一些内容\multicolumn
,从而引发以下错误:
! Misplaced \omit.
\multispan ->\omit
\@multispan
l.20 \condrow{m}{condrow multi}
% FAILS
加在\\
前面\multicolumn
会使错误消失,但会插入一个空行。问题放错了 \omit。\multispan 和 \newcommand类似。但是,答案并不能解决我的问题。我尝试使用该ifthen
包进行分支,但没有成功。
任何想法如何解决这一问题?
答案1
解决方案expl3
:
\documentclass[letterpaper,10pt]{article}
\usepackage{xparse}
\ExplSyntaxOn
\DeclareExpandableDocumentCommand{\condrow}{ m m }
{
\str_case:nnF { #1 }
{
{ l } { #2 & & \\ }
{ r } { & & #2 \\ }
{ c } { & #2 & \\ }
{ m } { \multicolumn{3}{c}{#2} \\ }
}
{ \PackageError{condrow}{Undefined~option:~#1}{<explanation>} }
}
\ExplSyntaxOff
\begin{document}
\begin{tabular}{|c|c|c|}
\condrow{l}{left}
\condrow{r}{right}
\condrow{c}{center}
\condrow{m}{condrow multi}
\end{tabular}
\end{document}
这样做的好处是更容易扩展以接受新的选项。
答案2
正如 Werner 所说,您需要一个可扩展的测试。由于您只是比较单个字母,因此替代方案\pdfstrcmp
是\if
\documentclass[letterpaper,10pt]{article}
\newcommand*{\condrow}[2]{%
\if l#1 #2 & & \\%
\else\if r#1 & & #2 \\%
\else\if c#1 & #2 & \\%
\else\if m#1\multicolumn{3}{c}{#2} \\%
\else\PackageError{condrow}{Undefined option: #1}{}%
\fi\fi\fi\fi%
}
\begin{document}
\begin{tabular}{|c|c|c|}
\condrow{l}{left}
\condrow{r}{right}
\condrow{c}{center}
\multicolumn{3}{c}{manual multi} \\ % WORKS
\condrow{m}{condrow multi} % WORKS
\end{tabular}
\end{document}
答案3
这与以下错误完全相同:放错了地方\omit
。\multispan
了\newcommand
- 只是不那么明显。问题是xstring
的\IfEqCase
不可扩展,因为它会进行赋值来执行比较。相反,使用来自测试两个完全展开的字符串是否相等,您可以利用 pdfTeX\pdfstrcmp
以可扩展的方式比较字符串:
\documentclass[letterpaper,10pt]{article}
\makeatletter
\newcommand*{\condrow}[2]{%
\ifnum\pdfstrcmp{#1}{l}=\z@ #2 & & \\
\else\ifnum\pdfstrcmp{#1}{r}=\z@ & & #2 \\
\else\ifnum\pdfstrcmp{#1}{c}=\z@ & #2 & \\
\else\ifnum\pdfstrcmp{#1}{m}=\z@ \multicolumn{3}{c}{#2} \\
\else\PackageError{condrow}{Undefined option: #1}{}%
\fi\fi\fi\fi%
}
\makeatother
\begin{document}
\begin{tabular}{|c|c|c|}
\condrow{l}{left}
\condrow{r}{right}
\condrow{c}{center}
\multicolumn{3}{c}{manual multi} \\ % WORKS
\condrow{m}{condrow multi} % WORKS
\end{tabular}
\end{document}
答案4
供参考,如果您使用{NiceTabular}
,nicematrix
及其内置命令\Block
而不是\multicolumn
,您可以直接获得所需的输出(因为\Block
是一个按原样工作的受保护命令)。
nicematrix
但是,由于底层使用了 PGF/Tikz 节点,因此您需要进行多次编译。
\documentclass[letterpaper,10pt]{article}
\usepackage{nicematrix}
\usepackage{xstring}
\newcommand*{\condrow}[2]{
\IfEqCase{#1}{
{l}{#2 & & \\}
{r}{ & & #2 \\}
{c}{ & #2 & \\}
{m}{\Block{1-3}{#2} & & \\}
}[\PackageError{condrow}{Undefined option: #1}{}]
}
\begin{document}
\begin{NiceTabular}{|c|c|c|}
\condrow{l}{left}
\condrow{r}{right}
\condrow{c}{center}
\multicolumn{3}{c}{manual multi} \\
\condrow{m}{condrow multi}
\end{NiceTabular}
\end{document}