5

So I'm trying to import a large list of values that are used throughout my report. However when i do this the results are always blank...

\documentclass{scrreprt}
\usepackage{csvsimple}
%
\csvloop{file={keyval.csv}, head to column names, command=%
    \expandafter\newcommand\csname \Key
    \endcsname{\Value}
}
%
\begin{document}
During test number TR-\testNumber{} a \vehicle{} was subject to etc.... 
\end{document}

and in the folder is the csv file; keyval.csv;

Key, Value
testNumber, 001
vehicle, Volkswagen Beetle

basically the result is;

During test number TR a was subject to etc...

6

Your problem is that you've defined \testNumber here to expand to \Value, whereas you want it to expand to what \Value was when you created it. That needs an \edef, or better a \protected@edef

\begin{filecontents*}{\jobname.csv}
Key, Value
testNumber, 001
vehicle, Volkswagen Beetle
\end{filecontents*}
\documentclass{scrreprt}

\usepackage{csvsimple}
\makeatletter
\csvloop{file={\jobname.csv}, head to column names, command=%
    \expandafter\protected@edef\csname \Key
    \endcsname{\Value}
}
\makeatother
\begin{document}
During test number TR-\testNumber{} a \vehicle{} was subject to etc.... 
\end{document}

The reason for this is that TeX is a macro expansion language. With

\expandafter\newcommand\csname \Key
\endcsname{\Value}

the \Key is expanded (by \csname) to give you \testNumber but the \Value is not. On the other hand, \edef forces expansion of the replacement text. The \protectd@edef version is safe with content that is made up of LaTeX macros, for example if you have any formatting in the CSV file.

  • Works perfectly! it is interesting that the returned value was blank, rather than an error in the log. – Daniel Myles Wood Sep 6 '15 at 14:26
3

You are forgetting to expand \Value, which can be easily done by adding a couple of \expandafter tokens. I prefer to separate things and hide the complicated code into a macro rather than the argument to \csvloop.

The idea is of exploiting the fact that \csname does full expansion, so an \expandafter in front of \endcsname is expanded, which triggers the expansion of the next one, which finally expands (once) \Value. Otherwise you'd essentially obtain \newcommand\testNumber{\Value}, so the current meaning of \Value would be used, not the one at definition time.

However, there's a small complication: \Value must be expanded twice, because the first level expansion of \Value is \csvcolii (an internal representation of the cell content). Not a problem: use a triple \expandafter sequence.

\begin{filecontents*}{\jobname.csv}
Key, Value
testNumber, 001
vehicle, Volkswagen Beetle
\end{filecontents*}

\documentclass{scrreprt}

\usepackage{csvsimple}

\newcommand{\definekeytovalue}[2]{%
  \expandafter\newcommand
    \csname#1\expandafter\expandafter\expandafter\endcsname
    \expandafter\expandafter\expandafter{#2}%
}

\csvloop{
  file={\jobname.csv},
  head to column names,
  command=\definekeytovalue{\Key}{\Value}
}

\begin{document}

During test number TR-\testNumber{} a \vehicle{} was subject to etc....

\end{document}

enter image description here

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.