3

I want to use some data, imported with csvsimple, in a table caption.

\begin{filecontents*}{data.csv}
column1,column2,column3
name1,val1a,val1b
name2,val2a,val2b
\end{filecontents*}

\documentclass{article}
\usepackage[utf8]{inputenc}
\usepackage{csvsimple}

\newcommand{\csvget}[3]{\csvreader[no head, filter equal={\thecsvinputline}{#2}]{#1}{}{#3}}

\begin{document}
\listoftables

\begin{table}
   \centering
   My Tabular
   \caption{A caption \csvget{data.csv}{2}{\csvcolii}}
\end{table}

\end{document}

Using the code from above I get an error like Argument of \@caption has an extra...
Any suggestions?

Thanks in advance
CX

3

This is a problem with fragile commands. See What is the difference between Fragile and Robust commands?

With e-tex compatible compiler you may use \newrobustcmd from etoolbox:

\begin{filecontents*}{data.csv}
column1,column2,column3
name1,val1a,val1b
name2,val2a,val2b
\end{filecontents*}

\documentclass{article}
\usepackage[utf8]{inputenc}
\usepackage{csvsimple}
\usepackage{etoolbox}

\newrobustcmd{\csvget}[3]{\csvreader[no head, filter equal={\thecsvinputline}{#2}]{#1}{}{#3}}

\begin{document}
\listoftables

\begin{table}
   \centering
   \csvautotabular{data.csv}
   \caption{A caption \csvget{data.csv}{2}{\protect\csvcolii}}
\end{table}

\end{document}

Without it you may use \DeclareRobustCommand

\begin{filecontents*}{data.csv}
column1,column2,column3
name1,val1a,val1b
name2,val2a,val2b
\end{filecontents*}

\documentclass{article}
\usepackage[utf8]{inputenc}
\usepackage{csvsimple}

\DeclareRobustCommand{\csvget}[3]{\csvreader[no head, filter equal={\thecsvinputline}{#2}]{#1}{}{#3}}

\begin{document}
\listoftables

\begin{table}
   \centering
   \csvautotabular{data.csv}
   \caption{A caption \csvget{data.csv}{2}{\protect\csvcolii}}
\end{table}

\end{document}

the result is:

result

  • Using your code-expamples I get strange results in the list of tables. any improvements? – cxkoda Nov 25 '13 at 8:28
  • @cxkoda I think I just found out what you mean with "strange results" You mean the text in the list of tables is different to the caption. I think I got a solution. Please test after I updated my solution. – someonr Nov 25 '13 at 10:36
  • I think, someone else might provide a better solution... – someonr Nov 25 '13 at 11:18
  • I am a little bit confused. Your answer solves the question in my humble opinion. There are no "strange results" anymore ... – Thomas F. Sturm Dec 5 '13 at 13:56
  • Good to hear that it is working. I had updated the answer (see under the answer at the field "edited date", also I said that I'll update the in a comment above) – someonr Dec 5 '13 at 21:28
1

edit (2017): the code was broken since xint 1.1 (2014/10/28) as from then on package xint does not load xinttools. Thus rather than \usepackage{xint}, one needed here \usepackage{xinttools}.

Here is some general purpose csv-file handling macro \ReadCSVfile {filename}\to \MACRO. Then \MACRO {i}{j} expands to the jth item of the ith row and you can do all you want in \caption's or whatever. The filename must be given with its extension.

csvcaption

Code relies on the macros of xint which have been very recently been moved to the xinttools package. But there is still at least one dependency of xinttools on xint due to some oversight, so we load xint here.

\documentclass{article}
\usepackage[utf8]{inputenc}
\usepackage{filecontents}
\begin{filecontents*}{data.csv}
column1,column2,column3
name1,val1a,val1b
name2,val2a,val2b
\end{filecontents*}

\usepackage{xinttools}

% VERY SIMPLE CSV HANDLING. Syntax:

% \ReadCSVfile {data.csv} \to \DATA

% \DATA WILL BE DEFINED AS A TWO ARGUMENTS COMMAND:

% \DATA {0}{0}: number of lines
% \DATA {i}{0}: number of items in i th line
% \DATA {i}{j}: j th item of i th line
% \DATA {0}{i}: the ith line as a list of braced items.

% WARNING: \DATA (or whatever it is called) WILL BE OVERWRITTEN.

\makeatletter
% example \ReadCSVfile {data.csv} \to \DATA
% WARNING: macro \DATA gets defined with no check if it already exists !!
\newcount\ReadCSV@linecount
\newcount\ReadCSV@itemcount
\newcommand\ReadCSVfile [3]{%
    \IfFileExists{#1}
    {%
      \edef\ReadCSV@restore{\endlinechar=\the\endlinechar\relax
                            \catcode`\noexpand\@=\the\catcode`\@\relax}%
      \endlinechar=-1 
      \makeatletter % in case csv file contains LaTeX macros with @ character
      \newread\ReadCSV@instream
      \openin\ReadCSV@instream\@filef@und
      \ReadCSV@linecount\z@
      \xintloop
         \read\ReadCSV@instream to\ReadCSV@oneline
      \unless\ifeof\ReadCSV@instream
         \advance\ReadCSV@linecount\@ne
         \ReadCSV@itemcount\z@
% we suppress all spaces around commas from the input file. Use braces around
% the item with spaces to force such spaces.
%
% the reason for such definition is for optimization in order for the conversion
% from  CSV format to be done only once. We take care not to expand the file
% contents, in case they have some LaTeX meaning.        
% 
         \toks@ \expandafter{\romannumeral0\expandafter\xintcsvtolist
                     \expandafter{\expandafter\space\ReadCSV@oneline}}%
         \expandafter
         \edef\csname CSV@\string#3@0.\the\ReadCSV@linecount\endcsname
                            {\the\toks@}%
         \xintFor* ####1 in {\the\toks@} \do
         {%
           \advance\ReadCSV@itemcount\@ne
           \expandafter
           \def\csname CSV@\string#3@\the\ReadCSV@linecount.%
                                     \the\ReadCSV@itemcount\endcsname
                  {####1}%
         }%
         \expandafter
         \def\csname CSV@\string#3@\the\ReadCSV@linecount.%
                                      0\expandafter\endcsname
                                       \expandafter{\the\ReadCSV@itemcount}%
      \repeat
      \closein\ReadCSV@instream
      \ReadCSV@restore
      \expandafter
      \edef\csname CSV@\string#3@0.0\endcsname {\the\ReadCSV@linecount}%
      \def#3####1####2%
      {\csname CSV@\string#3@\the\numexpr####1.\the\numexpr####2\endcsname }%
    }
    {\typeout{No file #1}}%
}


\ReadCSVfile {data.csv} \to \DATA

% \DATA {0}{0}: number of lines
% \DATA {i}{0}: number of items in i th line
% \DATA {i}{j}: j th item of i th line
% \DATA {0}{i}: the ith line as a list of *braced* items.

% spaces around commas in input file are REMOVED.


\begin{document}
\listoftables
\bigskip

\begin{table}
   \centering
   My Tabular
   \caption{Second of second line \DATA {2}{2}}
\end{table}

\begin{table}
   \centering
   My Tabular
   \caption{Third of first line \DATA {1}{3}}
\end{table}

The data file contains \DATA {0}{0} lines. 

\newcounter{linecount}
\setcounter{linecount}{0}

% Note: we must use \endgraf because \xintloop currently does not accept \par.
\xintloop
\stepcounter{linecount}
The line numbered \arabic{linecount} contains \DATA {\value{linecount}}{0}
entries. Here they are:%
\xintFor* #1 in {\xintSeq {1}{\DATA {\value{linecount}}{0}}} 
\do 
  { \DATA {\value{linecount}}{#1},} and that's
  it for that line.\endgraf
\ifnum\value{linecount}<\DATA{0}{0}
\repeat

\bigskip

We can also handle files with lines of different lengths.

\begin{filecontents*}{data2.csv}
column1,column2,column3,column4
name1,val1a,val1b
name2,val2a,val2b,X,Y,Z
a,b,c,d,e,f,g
\end{filecontents*}

\ReadCSVfile {data2.csv} \to \DATAII

\setcounter{linecount}{0}

% Note: we must use \endgraf because \xintloop currently does not accept \par.
\xintloop
\stepcounter{linecount}
The line numbered \arabic{linecount} contains \DATAII {\value{linecount}}{0}
entries. Here they are: 
\xintListWithSep{, }{\DATAII {0}{\value{linecount}}}.\endgraf 
\ifnum\value{linecount}<\DATAII {0}{0}
\repeat

\setcounter{linecount}{0}

Here is a nice Plain \TeX{} alignment with this data:

\tabskip1em
\fbox{\vbox{\halign{&\hfil#\hfil\cr
        \xintloop 
        \ifnum\value{linecount}<\DATAII {0}{0}
        \stepcounter{linecount}%
        \xintListWithSep {&}{\DATAII {0}{\value{linecount}}}%
        \cr 
        \repeat
}}}

\medskip \LaTeX{}'s tabulars can be used with lines
having a varying number of items but one must know the maximal number of items
from all rows (I think).

\end{document}

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.