因此,搜索了几个小时后,我很惊讶没有找到任何有用的解决方案。
我使用 导入 CSV 表datatool
。该表仅包含 3 个窄列,但我得到了很多行。我按照文档中的示例将两行放在一个表行中并排显示。
到目前为止,一切正常,但不幸的是,值是从左到右读取的,而不是从左侧从上到下读取,然后从右半部分从上到下读取。
让我说明一下我的问题:
|---|---|---|---|
| # |foo| # |foo|
|===|===|===|===|
| 1 |abc| 2 |def|
| 3 |ghi| 4 |jkl|
| 5 |mno| 6 |pqr|
|---|---|---|---|
这就是按照文档(示例 8,第 47 页)现在的情况datatool.pdf
)。
我想要的是
|---|---|---|---|
| # |foo| # |foo|
|===|===|===|===|
| 1 |abc| 4 |jkl|
| 2 |def| 5 |mno|
| 3 |ghi| 6 |pqr|
|---|---|---|---|
是否有机会修改该示例以提供像那样的输出?
最小示例
\documentclass[a4paper]{article}
\usepackage{datatool}
\begin{document}
\DTLsetseparator{;}
\DTLloaddb[noheader,keys={id,item}]{test_db}{test.csv}
\begin{table}[htbp]
\caption{Two database rows per tabular row}
\centering
\begin{tabular}{cc|cc}
\bfseries ID &
\bfseries Item &
\bfseries ID &
\bfseries Item
\DTLforeach*{test_db}{\id=id,\item=item}{%
\DTLifoddrow{\\}{&}%
\id & \item}%
\end{tabular}
\end{table}
\end{document}
充满test.csv
以下内容
1;abc
2;def
3;ghi
4;jkl
5;mno
6;pqr
答案1
\documentclass[a4paper]{article}
\usepackage{datatool}
\begin{document}
\DTLsetseparator{;}
\DTLloaddb[noheader,keys={id,item}]{test_db}{test.csv}
\begin{table}[htbp]
\count2=\DTLrowcount{test_db}
\count4 = \count2
\divide\count4 by 2
\count2=\count4
\advance\count2 by 1
\caption{Two database rows per tabular row}
\centering
\begin{tabular}{cc|cc}
\bfseries ID &
\bfseries Item &
\bfseries ID &
\bfseries Item
\DTLforeach*[\id<\count2]{test_db}{\id=id,\item=item}{%
\\
\id & \item
\count0=\id
\advance\count0 by \count4
\DTLforeach*[\id=\count0]{test_db}{\id=id,\item=item}{%
&\id &\item}
}
\end{tabular}
\end{table}
\end{document}
答案2
在 David Carlisle 的帮助下,我成功解决了这个问题。我稍微修改了他的代码,使其也支持 CSV 文件中奇数行。我的修改可能不是最好的方法,但我才刚刚开始使用 LaTeX,它与我习惯的编程方式完全不同。
\documentclass[a4paper]{article}
\usepackage{datatool}
\begin{document}
\DTLsetseparator{;}
\DTLloaddb[noheader,keys={id,item}]{test_db}{test.csv}
\DTLrowcount{test_db}
\begin{table}[htbp]
\count2=\DTLrowcount{test_db}
\count4 = \count2
\divide\count4 by 2
\count2=\count4
%%% modification start
\count10=\count2
\advance\count10 by \count4
\ifnum\count10=\DTLrowcount{test_db}
%even number of entries
\advance\count2 by 1
\else
%odd number of entries
\advance\count2 by 2
\advance\count4 by 1
\fi
%%% modification end
\caption{Two database rows per tabular row}
\centering
\begin{tabular}{cc|cc}
\bfseries ID &
\bfseries Item &
\bfseries ID &
\bfseries Item
\DTLforeach*[\id<\count2]{test_db}{\id=id,\item=item}{%
\\
\id & \item
\count0=\id
\advance\count0 by \count4
\DTLforeach*[\id=\count0]{test_db}{\id=id,\item=item}{%
&\id &\item}
}
\end{tabular}
\end{table}
\end{document}
答案3
这里有一个替代方法,它更有效,因为它只使用简单\loop
而不是嵌套的实例\DTLforeach*
:
\documentclass[a4paper]{article}
\usepackage{datatool}
\begin{document}
\DTLsetseparator{;}
\DTLloaddb[noheader,keys={id,item}]{test_db}{test.csv}
\newcount\mididx
\mididx=\numexpr\DTLrowcount{test_db}/2\relax
\begin{table}[htbp]
\caption{Two database rows per tabular row}
\centering
\newcommand\tabcontents{\bfseries ID & \bfseries Item &
\bfseries ID & \bfseries Item}%
\count2=0\relax
\loop
\advance\count2 by 1\relax
\DTLassign{test_db}{\count2}{\Id=id,\Item=item}%
\eappto\tabcontents{\noexpand\\\expandonce\Id \noexpand & \expandonce\Item}%
\count4=\numexpr\count2+\mididx\relax
\ifnum\count4>\DTLrowcount{test_db}
\else
\DTLassign{test_db}{\count4}{\Id=id,\Item=item}%
\eappto\tabcontents{\noexpand& \expandonce\Id \noexpand& \expandonce\Item}%
\fi
\ifnum\count2<\mididx
\repeat
\begin{tabular}{cc|cc}
\tabcontents
\end{tabular}
\end{table}
\end{document}
为了避免在表格上下文中循环的复杂性,这用于\loop
构造一个控制序列(\tabcontents
)来包含表格内容,然后将其放置\tabcontents
在tabular
环境中。(\eappto
由 提供etoolbox
,由 自动加载datatool
。)