![datatool DTLgetvalue 使用 foreachitem](https://linux22.com/image/411033/datatool%20DTLgetvalue%20%E4%BD%BF%E7%94%A8%20foreachitem.png)
以下代码应该从 mydata.csv 的第一行获取值,然后将值复制到新的空行。
我正在使用 foreachitem 将键传递给 DTLgetvalue 函数。它可以编译,但它不会从 itemlist 中获取每个键,而是似乎使用项目列表的最后一个键。我是否遗漏了有关如何将 listofitems 传递给 DTLfuction 的某些信息,或者 \tmp 变量是否未刷新?
\documentclass[a4paper,10pt]{article}
\usepackage{datatool}
\usepackage{listofitems}
\usepackage{tabularx}
\begin{filecontents*}{mydata.csv}
ColA, ColB, ColC
John, Doe, 1
Eve, Johansen, 2
Scott, Great, 3
\end{filecontents*}
\DTLloaddb[keys={ColA,ColB,ColC}]{mydata}{mydata.csv}
\readlist\keylist{ColA,ColB,ColC} %%% making a list of header-keys
\newcommand{\addemptyrow}{%
\DTLnewrow{mydata}%%%
\foreachitem\key\in\keylist{%
\DTLgetvalue{\tmp}{mydata}{1}{\dtlcolumnindex{mydata}{\key}}%
\DTLnewdbentry{mydata}{\key}{\tmp}}
}
\begin{document}
\DTLdisplaydb{mydata}
\addemptyrow{}
\DTLdisplaydb{mydata}
\end{document}
答案1
所以,我解决了。这是使用 expand 的问题。仍然没有完全理解 expand 的概念,但找到了一个类似的旧线程这里
因此,如果我在宏中添加 \dtlexpandnewvalue,上述操作即可奏效
\readlist\keylist{ColA,ColB,ColC}
\newcommand{\addemptyrow}{%
\DTLnewrow{mydata}%%%
\dtlexpandnewvalue
\foreachitem\key\in\keylist{%
\DTLgetvalue{\tmp}{mydata}{1}{\dtlcolumnindex{mydata}{\key}}%
\DTLnewdbentry{mydata}{\key}{\tmp}}
\dtlnoexpandnewvalue
}
如果没有 \dtlexpandnewvalue,我只会看到 \tmp 的最后一个值(即“1”)
使用 \dtleexpandnewvalue 解决了这个问题
答案2
问题是它\tmp
没有得到扩展,因此您实际上是\tmp
在每个单元格中添加。
有多种方法可以解决这个问题。这里我提出了一种基于 的另一种方法,xparse
这种expl3
方法也使列表循环的管理更加容易。
\begin{filecontents*}{\jobname.csv}
ColA, ColB, ColC
John, Doe, 1
Eve, Johansen, 2
Scott, Great, 3
\end{filecontents*}
\documentclass[a4paper,10pt]{article}
\usepackage{datatool}
\usepackage{xparse}
\ExplSyntaxOn
\NewDocumentCommand{\makelist}{mm}
{
\clist_clear_new:c { l__sorenj_list_#1_clist }
\clist_set:cn { l__sorenj_list_#1_clist } { #2 }
}
\NewDocumentCommand{\maplist}{mm}
{
\cs_set_protected:Nn \__sorenj_list_map:n { #2 }
\clist_map_function:cN { l__sorenj_list_#1_clist } \__sorenj_list_map:n
}
\NewDocumentCommand{\xDTLnewdbentry}{mmm}
{
\exp_args:Nnno \DTLnewdbentry { #1 } { #2 } { #3 }
}
\ExplSyntaxOff
\DTLloaddb[keys={ColA,ColB,ColC}]{mydata}{\jobname.csv}
\makelist{keylist}{ColA,ColB,ColC} %%% making a list of header-keys
\begin{document}
\DTLdisplaydb{mydata}
\DTLnewrow{mydata}
\maplist{keylist}{%
\DTLgetvalue{\tmp}{mydata}{1}{\dtlcolumnindex{mydata}{#1}}%
\xDTLnewdbentry{mydata}{#1}{\tmp}%
}
\DTLdisplaydb{mydata}
\end{document}
没有\key
必要,你只需用 表示当前项目。注意,如果你将循环嵌入另一个宏的定义中,#1
它应该变成。##1
的扩展\tmp
是唯一需要关心的另一件事,它的工作是\exp_args:NnnV
跳过第一个标记(在本例中为\DTLnewdbentry
)和接下来的两个支撑组,以扩展下一个标记(即)的值\tmp
。