1

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}

    \DTLloaddb{Datos}{datos.csv}
    \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:

Result when compiling this MWE

  • 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
1

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}

\DTLloaddb{Datos}{\jobname.csv}
\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.

enter image description here

  • 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
  • 1
    @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

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.