# Using “datatool” to assign values to newly created commands ends filling all with the last value

I'm trying to create new commands by taking their values via a CSV file and datatool to load them into a DB. The problem is that every created command with this process ends with the values assigned to the last entry in the DB.

MWE

Here I put both the CSV used and a MWE (thanks to Werner for the "command wrapper", whereabouts here):

The CSV file:

Campo,Valor,Aux
hallo,"Cmon",
another,"Piece",
whuzzat,"abc",


The LaTeX document used to load the CSV file:

\documentclass{article}

\usepackage{etoolbox}
\usepackage{datatool}

\newcommand{\assignto}[2]{%
\ifcsdef{#2}{%
\csdef{#1}{\csuse{#2}}%
}{%
\csdef{#1}{#2}%
}%
}

\begin{document}
\section*{Hard-coded variables}

\newcommand{\abc}{ABC}
\assignto{AAA}{aaa}\AAA\ %end to denote space
\assignto{BBB}{abc}\BBB

\section*{DB variables}

\DTLforeach{Datos}{\campo=Campo,\valor=Valor,\valorb=Aux}{%
\assignto{\campo}{\valor}
}

\hallo\ % It should be "Cmon"
\another\ % It should be "Piece"
\whuzzat\ % It should be "\abc", i.e. "ABC"
\end{document}


Output:

• You need to expand the valor e.g. with \csedef, but I do find your code highly dangerous. You are creating commands without checking if you are overwriting existing commands. – Ulrike Fischer Sep 21 '15 at 14:24
• @UlrikeFischer Indeed, it was just for the sake of the example. I was already told that using prefixes (namespacing them) should be taken into account to avoid such editing. – logo_writer Sep 21 '15 at 14:26

You're basically doing

\def\hallo{\valor}


and you should expand \valor before doing the definition:

\DTLforeach{Datos}{\campo=Campo,\valor=Valor,\valorb=Aux}{%
\expandafter\assignto\expandafter{\expandafter\campo\expandafter}\expandafter{\valor}
}


Of course there are better and shorter ways; for instance

\newcommand\assignto[2]{\expandafter\assigntoaux\expandafter{#2}{#1}}
\newcommand{\assigntoaux}[2]{%
\ifcsdef{#1}{%
\csdef{#2}{\csuse{#1}}%
}{%
\csdef{#2}{#1}%
}%
}


just switching the arguments.

An even better way is with xparse and expl3:

\begin{filecontents*}{\jobname.csv}
Campo,Valor,Aux
hallo,"Cmon",
another,"Piece",
whuzzat,"abc",
\end{filecontents*}

\documentclass{article}

\usepackage{datatool}
\usepackage{xparse}

\ExplSyntaxOn
\NewDocumentCommand{\assignto}{smm}
{
\IfBooleanTF{#1}
{
\logowriter_assignto:no { #2 } { #3 }
}
{
\logowriter_assignto:nn { #2 } { #3 }
}
}
\cs_new_protected:Nn \logowriter_assignto:nn
{
\cs_new:cpn { #1 } { #2 }
}
\cs_generate_variant:Nn \logowriter_assignto:nn { no }
\ExplSyntaxOff

\begin{document}
\section*{Hard-coded variables}

\newcommand{\abc}{ABC}
\assignto{AAA}{aaa}\AAA\ %end to denote space
\assignto{BBB}{abc}\BBB

\section*{DB variables}

\DTLforeach{Datos}{\campo=Campo,\valor=Valor,\valorb=Aux}{%
\assignto*{\campo}{\valor}
}

\hallo\ % It should be "Cmon"
\another\ % It should be "Piece"
\whuzzat\ % It should be "\abc", i.e. "ABC"

\end{document}


Note that \assignto* expands once the second argument, before doing the definition, which is the same as the long chain of \expandafter tokens above, but much simpler.

• Wow, you're pretty fast! Thanks, I've tested it and works! One question, though: Does expandafter gets the value of the command before or after processing the line? – logo_writer Sep 21 '15 at 14:27
• @logo_writer When expanding \assignto. It does nothing at definition time, it just gets stored. – egreg Sep 21 '15 at 14:30
• So that's why the value is lost when not expanding. Pretty impressive that there are plenty of options, though. Why did you switch the arguments in the second solution? – logo_writer Sep 21 '15 at 14:40
• @logo_writer Just to use less \expandafter's – egreg Sep 21 '15 at 14:43
• Thanks! If I have two normal values instead, how do I expand them with expandafter? That is, suppose the second command is not a command by itself, but just like #2 in this example. – logo_writer Sep 21 '15 at 14:56