我正在寻找一种方法来测试列中的(非键)值是否存在。我基本上想检查
\DTLfetch{db name}{col1 name}{col1 value}{col2 name}
给我一个来自数据库的值或“未定义值”,因为“col1 值”不存在于此列中。不是因为列中的特定值为空,而是因为查询的值不是数据库的一部分。datatool 有一个函数
\DTLifhaskey{db name}{key}{true}{false}
检查“col1 名称”和“col2 名称”,但我似乎找不到检查“col1 值”的简单方法。
我也尝试捕获“未定义值”返回,但到目前为止没有任何效果,并且在返回“未定义值”时,它已经抛出了错误。因此,在调用 fetch 之前识别查询值“col1 值”不是 csv 的一部分会更好。
答案1
宏
\DTLgetvalueforkey{⟨cmd⟩}%
{⟨column2 name⟩}%
{⟨db name⟩}%
{⟨column1 name⟩}%
{⟨column1 value⟩}%
在数据库中⟨db name⟩
寻找名称为 的列⟨column1 name⟩
首次包含值的行。在该行中查找⟨column1 value⟩
属于 的值,并定义宏以扩展该值。⟨column2 name⟩
⟨cmd⟩
如果⟨column1 value⟩
由于某种原因无法找到,则将宏⟨cmd⟩
定义为产生\@dtlnovalue
(,而这通常会扩展为Undefined Value
)。
因此⟨cmd⟩
可以通过 来使用和/或检查。\DTLifnull{⟨cmd⟩}{⟨true part⟩}{⟨false part⟩}
因此,
\DTLfetch{⟨db name⟩}%
{⟨column1 name⟩}%
{⟨column1 value⟩}%
{⟨column2 name⟩}%
你可以做类似的事情
\DTLgetvalueforkey{⟨cmd⟩}%
{⟨column2 name⟩}%
{⟨db name⟩}%
{⟨column1 name⟩}%
{⟨column1 value⟩}%
⟨cmd⟩
或者
\DTLgetvalueforkey{⟨cmd⟩}%
{⟨column2 name⟩}%
{⟨db name⟩}%
{⟨column1 name⟩}%
{⟨column1 value⟩}%
\DTLifnull{⟨cmd⟩}{⟨tokens in case of value not being available⟩}{⟨cmd⟩}%
或者
\DTLgetvalueforkey{⟨cmd⟩}%
{⟨column2 name⟩}%
{⟨db name⟩}%
{⟨column1 name⟩}%
{⟨column1 value⟩}%
\DTLifnull{⟨cmd⟩}{⟨tokens in case of value not being available⟩}%
{⟨tokens in case of value being available⟩}%
如果您坚持“手动”捕捉情况,那么您可以针对相关数据库值不可用的不同原因引入分支:
\show\DTLfetch
产量:
> \DTLfetch=\long macro:
#1#2#3#4->\edtlgetrowforvalue {#1}{\dtlcolumnindex {#1}{#2}}{#3}\dtlgetentryfro
mcurrentrow {\dtlcurrentvalue }{\dtlcolumnindex {#1}{#4}}\dtlcurrentvalue .
示例 21(将两个数据库合并为一个表)数据工具包 2.32 版用户手册说:
\DTLfetch{students}{regnum}{\RegNum}{forename}
相当于
\edtlgetrowforvalue{students}{\dtlcolumnindex{students}{regnum}}{\RegNum}%
\dtlgetentryfromcurrentrow{\dtlcurrentvalue}{\dtlcolumnindex{students}{forename}}%
\dtlcurrentvalue
部分 ”6.11.1 对当前行进行操作“datatool bundle 2.32 版用户手册中写道:
\dtlgetrowindex{⟨row cs⟩}{⟨db name⟩}{⟨col idx⟩}{⟨value⟩}
类似于,\DTLgetrowindex
但如果未找到匹配项,则不会产生错误。您可以使用来测试结果。\ifx⟨row cs⟩\dtlnovalue
\dtlcurrentvalue
您可以测试是否产生空值以及是否为空值,而不是传递:\DTLifnull{⟨cmd⟩}{⟨true part⟩}{⟨false part⟩}
\dtlcurrentvalue
\ifx⟨row cs⟩\dtlnovalue
⟨row cs⟩
%\DTLfetchifnull{<db name>}%
% {<column1 name>}%
% {<column1 value>}%
% {<column2 name>}%
% {<tokens in case <column2-value> is not a null-value>}%
% {<tokens in case <column2-value> is a null-value>}%
% {<tokens in case <column1-value> does not exist>}%
%
% Both with <tokens in case <column2-value> is not a null-value> and with
% <tokens in case <column2-value> is a null-value> the macro
% \dtlcurrentvalue is defined to yield the value of the column whose name
% is <column2 name>.
%
\makeatletter
\@ifundefined{NewDocumentCommand}%
{\newcommand\DTLfetchifnull[7]}%
{\NewDocumentCommand\DTLfetchifnull{mmmmmmm}}%
{%
\begingroup
\protected@edef\@dtl@dogetrowforvalue{%
\endgroup\noexpand\dtlgetrowindex{\noexpand\dtl@rowidx}{#1}{\dtlcolumnindex{#1}{#2}}{#3}%
}\@dtl@dogetrowforvalue
\ifx\dtl@rowidx\dtlnovalue\expandafter\@secondoftwo\else\expandafter\@firstoftwo\fi
{%
\edtlgetrowforvalue{#1}{\dtlcolumnindex{#1}{#2}}{#3}%
\dtlgetentryfromcurrentrow{\dtlcurrentvalue}{\dtlcolumnindex{#1}{#4}}%
\DTLifnull{\dtlcurrentvalue}{#6}{#5}%
}{%
#7%
}%
}%
\makeatother
下面的例子说明了 的用法\DTLfetchifnull
:
%=====Let LaTeX create a .csv-file holding a database.=====================
% This could as well be done via export to .csv-file by a
% professional database management system
\begin{filecontents*}{database.csv}
PrimaryKey,FirstName,LastName
1,Homer,Simpson
2,Ned,Flanders
3,The Crazy Cat Lady
4,Clancy,Wiggum
5,Moe,Szyslak
6,Barney,Gumble
\end{filecontents*}
%==========================================================================
\documentclass{article}
\usepackage{datatool}
%\DTLfetchifnull{<db name>}%
% {<column1 name>}%
% {<column1 value>}%
% {<column2 name>}%
% {<tokens in case <column2-value> is not a null-value>}%
% {<tokens in case <column2-value> is a null-value>}%
% {<tokens in case <column1-value> does not exist>}%
%
% Both with <tokens in case <column2-value> is not a null-value> and with
% <tokens in case <column2-value> is a null-value> the macro
% \dtlcurrentvalue is defined to yield the value of the column whose name
% is <column2 name>.
%
\makeatletter
\@ifundefined{NewDocumentCommand}%
{\newcommand\DTLfetchifnull[7]}%
{\NewDocumentCommand\DTLfetchifnull{mmmmmmm}}%
{%
\begingroup
\protected@edef\@dtl@dogetrowforvalue{%
\endgroup\noexpand\dtlgetrowindex{\noexpand\dtl@rowidx}{#1}{\dtlcolumnindex{#1}{#2}}{#3}%
}\@dtl@dogetrowforvalue
\ifx\dtl@rowidx\dtlnovalue\expandafter\@secondoftwo\else\expandafter\@firstoftwo\fi
{%
\edtlgetrowforvalue{#1}{\dtlcolumnindex{#1}{#2}}{#3}%
\dtlgetentryfromcurrentrow{\dtlcurrentvalue}{\dtlcolumnindex{#1}{#4}}%
\DTLifnull{\dtlcurrentvalue}{#6}{#5}%
}{%
#7%
}%
}%
\makeatother
\DTLloadrawdb{Simpsons}{database.csv}
\begin{document}
\DTLfetchifnull{Simpsons}%
{FirstName}%
{The Crazy Cat Lady}%
{LastName}%
{The last name of the Crazy Cat Lady is \dtlcurrentvalue.}%
{The Crazy Cat Lady dosen't have a last name.}%
{There is no First Name ``Crazy Cat Lady'' in the database.}%
\DTLfetchifnull{Simpsons}%
{FirstName}%
{Homer}%
{LastName}%
{The last name of Homer is \dtlcurrentvalue.}%
{Homer dosen't have a last name.}%
{There is no First Name ``Homer'' in the database.}%
\DTLfetchifnull{Simpsons}%
{FirstName}%
{Marge}%
{LastName}%
{The last name of Marge is \dtlcurrentvalue.}%
{Marge dosen't have a last name.}%
{There is no First Name ``Marge'' in the database.}%
\end{document}