![使用 `ifthenelse` 将两个相关函数合并为一个](https://linux22.com/image/282113/%E4%BD%BF%E7%94%A8%20%60ifthenelse%60%20%E5%B0%86%E4%B8%A4%E4%B8%AA%E7%9B%B8%E5%85%B3%E5%87%BD%E6%95%B0%E5%90%88%E5%B9%B6%E4%B8%BA%E4%B8%80%E4%B8%AA.png)
这个问题基于 Peter Grill 的回答“包括主表的行的表”。。
该函数PrintDTLTable
在 Peter 的原始答案中。我想要一个可以遍历所有行的版本,因此我将其稍微修改为PrintDTLTableDefault
,它没有行 ID 参数。和 都PrintDTLTable
按PrintDTLTableDefault
预期工作。
我认为将它们组合成一个函数更有意义,所以我尝试使用,ifthenelse
结果得到了
PrintDTLTableCombined
。这给出了错误
ERROR: Argument of \isempty has an extra }.
我没有看到任何明显的语法或使用错误。与 LaTeX 一样,错误可能与错误消息完全无关。我不需要使用ifthenelse
;其他东西也可以。
\documentclass{article}
\usepackage{array}
\usepackage{multirow}
\usepackage{datatool}
\usepackage{longtable}
\usepackage{filecontents}
\usepackage{xifthen}
\newcommand{\colhead}[1]{\multicolumn{1}{>{\bfseries}l}{#1}}
\newcounter{tabenum}\setcounter{tabenum}{0}
\newcommand{\nextnuml}[1]{\refstepcounter{tabenum}\thetabenum.\label{#1}}
\begin{filecontents*}{foo.dat}
Hammer001, Hammer, 1 , 0 , 1 , 10 , 1 , \multirow{2}{2in}{light (add some words here to wrap around)}\\
Hammer002, Hammer, 2 , 0 , 1 , 10 , 1 , heavy
Hammer003, Hammer, 3 , 0 , 1 , 10 , 1 , really heavy
Longsword001,Longsword, 1 , -1 , 2 , 75 , 2 , one-handed
Longsword002,Longsword, 2 , -1 , 2 , 75 , 2 , two-handed
Longsword003,Longsword, 3 , -1 , 2 , 75 , 2 , three-handed
\end{filecontents*}
\newcommand{\PrintDTLTable}[2]{%
% #1 = database to search
% #2 = list of rowIDs
\begin{tabular}{c c c c c c c p{3.0cm}}
& \colhead{Label} & \colhead{Cost} & \colhead{Weight} & \colhead{PropA} & \colhead{PropB} & \colhead{PropC} & \colhead{Description}\\\hline
\DTLforeach[\DTLisSubString{#2}{\RowID}]{#1}{%
\RowID=RowID,%
\Label=Label,%
\Cost=Cost,%
\Weight=Weight,%
\PropA=PropA,%
\PropB=PropB,%
\PropC=PropC,%
\Description=Description%
}{%
\nextnuml{\RowID} & \Label &\Cost & \Weight & \PropA & \PropB & \PropC & \Description \\
}%
\end{tabular}
}%
\newcommand{\PrintDTLTableDefault}[1]{%
% #1 = database to search
\begin{longtable}{c c c c c c c p{3.0cm}}
& \colhead{Label} & \colhead{Cost} & \colhead{Weight} & \colhead{PropA} & \colhead{PropB} & \colhead{PropC} & \colhead{Description}\\\hline
\DTLforeach[\boolean{true}]
{#1}{%
\RowID=RowID,%
\Label=Label,%
\Cost=Cost,%
\Weight=Weight,%
\PropA=PropA,%
\PropB=PropB,%
\PropC=PropC,%
\Description=Description%
}{%
\nextnuml{\RowID} & \Label &\Cost & \Weight & \PropA & \PropB & \PropC & \Description \\
}%
\end{longtable}
}%
\newcommand{\PrintDTLTableCombined}[2][]{%
% #1 = list of rowIDs
% #2 = database to search
\begin{longtable}{c c c c c c c p{3.0cm}}
& \colhead{Label} & \colhead{Cost} & \colhead{Weight} & \colhead{PropA} & \colhead{PropB} & \colhead{PropC} & \colhead{Description}\\\hline
\DTLforeach
[\ifthenelse{\isempty{#1}}{\boolean{true}}{\DTLisSubString{#1}{\RowID}}]
{#2}{%
\RowID=RowID,%
\Label=Label,%
\Cost=Cost,%
\Weight=Weight,%
\PropA=PropA,%
\PropB=PropB,%
\PropC=PropC,%
\Description=Description%
}{%
\nextnuml{\RowID} & \Label &\Cost & \Weight & \PropA & \PropB & \PropC & \Description \\
}%
\end{longtable}
}%
\begin{document}
% \DTLsetseparator{&}% Define separator of the data
\DTLloaddb[noheader,keys={RowID,Label,Cost,Weight,PropA,PropB,PropC,Description}]{myDB}{foo.dat}
%\PrintDTLTable{myDB}{Hammer001,Hammer003,Longsword003}
%\PrintDTLTableDefault{myDB}
\PrintDTLTableCombined{myDB}
This is a reference to ~\ref{Hammer003}.
\end{document}
更新:@Werner 的宏对我有用。但是,我仍然想知道是什么导致我的尝试失败;也许这会很有启发。LaTeX 对初学者来说很令人沮丧,部分原因是对于非专家来说,它经常似乎无法调试。
答案1
当你使用以下命令执行“检查空参数”时,它会起作用
% http://tex.stackexchange.com/q/308/5764
\makeatletter
\def\ifemptyarg#1{%
\if\relax\detokenize{#1}\relax % H. Oberdiek
\expandafter\@firstoftwo
\else
\expandafter\@secondoftwo
\fi}
\makeatother
而不是xifthen
\ifthenelse
:
\newcommand{\PrintDTLTableCombined}[2][]{%
% #1 = list of rowIDs
% #2 = database to search
\begin{longtable}{c c c c c c c p{3.0cm}}
& \colhead{Label} & \colhead{Cost} & \colhead{Weight} & \colhead{PropA} & \colhead{PropB} & \colhead{PropC} & \colhead{Description}\\\hline
\DTLforeach
[\ifemptyarg{#1}{\boolean{true}}{\DTLisSubString{#1}{\RowID}}]
{#2}{%
\RowID=RowID,%
\Label=Label,%
\Cost=Cost,%
\Weight=Weight,%
\PropA=PropA,%
\PropB=PropB,%
\PropC=PropC,%
\Description=Description%
}{%
\nextnuml{\RowID} & \Label &\Cost & \Weight & \PropA & \PropB & \PropC & \Description \\
}%
\end{longtable}
}%
检查空参数有时会有问题,因为某些用途可能需要赋值,这是不允许的。
分析为什么你的方法不起作用是因为datatool
评估条件。内部\DTLforeach[#1]{#2}{#3}{#4}
是一个测试
\ifthenelse{#1}{<true>}{<false>}
这datatool
用户指南支持这一点(部分5.4 迭代数据库,第 50 页):
\DTLforeach[<condition>]{<db name>}{<assign list>}{<text>}
可选参数
<condition>
是 允许的形式的条件\ifthenelse
。这包括包提供的命令ifthen
(例如\not
、\and
、\or
),以及 2.2 节中描述的命令。 的默认<condition>
值为\boolean{true}
。
因此,实际上您要实现的是一个嵌套条件,类似于
\ifthenelse{\ifthenelse{<condition>}{<trueA>}{<falseA>}}{<trueB>}{<falseB>}
重现该问题的最小示例如下
\documentclass{article}
\usepackage{xifthen}% http://ctan.org/pkg/xifthen
\begin{document}
\ifthenelse{\ifthenelse{\boolean{true}}{\boolean{true}}{\boolean{false}}}{A}{B}
\end{document}
虽然上面的内容(逻辑上)应该输出A
为(因为嵌套条件应该输出\boolean{true}
,其求值为真,应该输出A
),但您会收到错误
! Argument of \boolean has an extra }.
<inserted text>
\par
l.4 ...an{true}}{\boolean{true}}{\boolean{false}}}
{A}{B}
除了使用不同的方法得出条件结果外,没有其他方法可以解决这个问题,因为您使用条件来决定是否打印行。也就是说,您无法在 之外评估条件\DTLforeach
。