6

So after searching for some hours I'm surprised that there wasn't any useful solution to find.

I import a CSV table using datatool. That table only consists of 3 narrow columns, but I got a lot of rows. I followed the example in the documentation to get two rows in one table row next to each other.

So far that works fine but unfortunately the values read from left to right and not left side top to down and then on the right half top to down.

Let me illustrate my Problem:

|---|---|---|---|
| # |foo| # |foo|
|===|===|===|===|
| 1 |abc| 2 |def|
| 3 |ghi| 4 |jkl|
| 5 |mno| 6 |pqr|
|---|---|---|---|

That's how it is now following the documentation (Example 8, page 47 in datatool.pdf).

What I want to have is

|---|---|---|---|
| # |foo| # |foo|
|===|===|===|===|
| 1 |abc| 4 |jkl|
| 2 |def| 5 |mno|
| 3 |ghi| 6 |pqr|
|---|---|---|---|

Is there any chance to modify that example to give an output like that?

Minimal example

\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}

With test.csv filled with the following

1;abc
2;def
3;ghi
4;jkl
5;mno
6;pqr
6

enter image description here

\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}
  • Thank you! Your answer helped me a lot. I modified your code a little bit to also support an odd number of rows in the CSV file. It probably could be done nicer, but I'm just starting to use LaTeX so I'm happy to just get it to work. – aaron Mar 13 '12 at 19:35
2

Table with odd number of rows

With the help of David Carlisle I managed to solve it. I modified his code a little bit to also support an odd number of rows in the CSV file. My modification is probably not the best way to do it, but I'm just getting started with LaTeX and it is so not like what I'm used to when it comes to programming.

\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}
0

Here's an alternative approach which is more efficient as it only uses a simple \loop rather than nested instances of \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}

image of document

To avoid complications of looping within a tabular context, this uses \loop to construct a control sequence (\tabcontents) to contain the tabular contents, and then it just places \tabcontents within the tabular environment. (\eappto is provided by etoolbox, which is automatically loaded by datatool.)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.