使用 datatool 从 CSV 文件中读取一行,然后使用文档中的变量?

使用 datatool 从 CSV 文件中读取一行,然后使用文档中的变量?

我不知道如何使用“datatool”从数据库中的一行读取变量,并将它们传递给我的文本进行格式化。我不想制作表格,但互联网上似乎只有这些示例。

我有一个 CSV 文件,内容如下:

name|points
John|172
Sue|120
Mike|64

盯着数据工具手册看了两天后,我取得了以下成功:

\documentclass{memoir}
\usepackage{datatool}
\DTLsetseparator{|}
\begin{document}
\DTLloaddb{players}{database.csv}
\DTLforeach*{players}{\name=name,\points=points}
\subsection{\name}
\textit{\points}
\end{document}

这会以我想要的格式打印所选变量,但只打印数据库中的最后一个条目。我猜“\dtlgetrowforvalue{players}{1}{John}”可用于在数据库中查找 John 的行,但我不明白如何将其与读取和显示变量的命令集成。

我不熟悉手册中使用的许多术语,也找不到我想要实现的示例,我通过反复试验来解决问题的尝试失败了。我不一定需要一个可行的示例,但我非常希望有人至少能告诉我适当的命令。

答案1

\DTLforeach需要三个强制参数,而不是像您的示例中那样需要两个。这修复了您的示例:

\documentclass{memoir}

\usepackage{datatool}
\DTLsetseparator{|}

\DTLloaddb{players}{database.csv}

\begin{document}

\DTLforeach*
{players}% database label
{\name=name,\points=points}% assignment
{% Stuff to do at each iteration:
  \subsection{\name}
  \textit{\points}
}

\end{document}

得出的结果为:

结果图像

编辑:

\DTLforeach是一个重复(循环)命令,旨在对每一行数据执行特定操作。如果您只想从一行数据中查找信息,则有多种方法可以做到这一点。以下是一些示例:

\documentclass{memoir}

\usepackage{datatool}
\DTLsetseparator{|}

\DTLloaddb{players}{database.csv}

\begin{document}

Sue's points: \DTLfetch{players}{name}{Sue}{points}.

Pull information from row 3.
\DTLassign{players}{3}{\name=name,\points=points}

Here's the information: Name: \name. Points: \points.

Pull information from the first row where the name column has the
value ``John''.
\DTLassignfirstmatch{players}{name}{John}{\name=name,\points=points}

Here's the information: Name (we already know this anyway): \name.
Points: \points.

\newcommand{\PlayerName}{John}
As above, but the required name (\PlayerName) is given by a command:
\xDTLassignfirstmatch{players}{name}{\PlayerName}{\name=name,\points=points}

Here's the information: Name (we already know this anyway): \name.
Points: \points.

\end{document}

得出的结果为:

结果图像

Sue 的分数:120。
从第 3 行提取信息。
以下是信息:姓名:Mike。分数:64。
从姓名列的值为“John”的第一行提取信息。
以下是信息:姓名(反正我们已经知道了):John。分数:172。
与上述相同,但所需的姓名(John)由命令提供:
以下是信息:姓名(反正我们已经知道了):John。分数:172。

答案2

2016 年 11 月解决方案(不使用datatool):

该解决方案使用我最近更新的readarray包,该包现在使用强大的listofitems包来解析和访问数据。

\documentclass{article}
\usepackage{filecontents}
\begin{filecontents*}{database.csv}
name,points,d3,d4,d5,d6,d7,d8,d9,d10,d11
John,172,yes,black,23,0.000,89,big,32,A,Z
Sue,120,no,red,26,0.002,97,medium,36,B,W
Mike,64,maybe,green,89,0.567,154,small,42,C,X 
\end{filecontents*}
\usepackage{readarray}[2016-11-07]
\usepackage{ifthen}
\newcounter{recordindex}
\newcommand\findrecord[1]{%
  \def\matchrecord{0}
  \setcounter{recordindex}{0}%
  \whiledo{\therecordindex<\datacellROWS}{%
    \stepcounter{recordindex}%
    \ifthenelse{\equal{#1}%
      {\datacell[\therecordindex,1]}}
    {\xdef\matchrecord{\therecordindex}\setcounter{recordindex}{\datacellROWS}}%
    {}%
  }%
}
\begin{document}
\readarraysepchar{,}
\readdef{database.csv}{\mydata}
\readarray\mydata\datacell[-,\ncols]

The whole array is\arraydump\datacell
\datacellROWS\ records total\par
\datacell[3,6] is the 6th cell of the 3rd row\par
\datacell[4,11] is the 11th cell of the 4th row\par
\findrecord{Sue}
\datacell[\matchrecord,4] is Sue's 4th data cell
\end{document}

在此处输入图片描述

我正在删除我之前的解决方案,因为它们依赖于我的tabstackenginereadarray包中的内部代码,而这在最近的包更新中已经发生了变化。

答案3

偶然中,我找到了一个解决方案。不过,我让它工作的方式似乎有点冗长,所以我认为可能还有更好的方法,只是我还没想出来。

数据库.csv...

name,points,other
John,172,yes
Sue,120,no
Mike,64,maybe

文档.tex...

\documentclass{memoir}
\usepackage{datatool}
\DTLloaddb{players}{database.csv}
\newcommand{\player}[1]{%
    \dtlgetrowforvalue{players}{\dtlcolumnindex{players}{name}}{#1}%
    \input{./template.tex}%
}
\begin{document}
\player{Sue}
\end{document}

模板.tex...

% read variables into commands
\dtlgetentryfromcurrentrow{\name}{1}
\dtlgetentryfromcurrentrow{\points}{2}
\dtlgetentryfromcurrentrow{\other}{3}

% use commands in text
\subsubsection{\name}
\textit{\points}
\other

相关内容