6

I have a csv with 2 rows. the first row contains names and the second row the value. i want to create variables (tried it with newcommand) that have the Name of the first row and define them with the value of the second row. the final csv will contain around 50 rows.

here's my Code: it seems that it overwrites the same variable again and again ...

\documentclass{scrartcl}

\usepackage[ngerman]{babel} 
\usepackage{filecontents}
\usepackage{datatool}
\DTLsetseparator{,} 


\begin{filecontents*}{Unnamed1.csv}
Voltage   ,   14 V
Current   ,   1  A
MoreText  ,   something more is written here
Date      ,   2017/03/08
\end{filecontents*}

\DTLloaddb{Test}{Unnamed1.csv}


\begin{document}

\DTLforeach{Test}{\name=name,\value=value}
{
\newcommand{\name}{\value}
}

\end{document}
4

(Rewritten answer now the question is clearer.)

The problem with

\DTLforeach{Test}{\name=name,\value=value}
{
\newcommand{\name}{\value}
}

Is that \name is repeatedly redefined on each iteration by the assignment. This also just tries to define \name rather than construct a control sequence formed from the definition of \name. The etoolbox package provides ways of defining a command given the name (without the initial backslash). For example, \csdef{Voltage}{14 V} defines the command \Voltage with the replacement text 14 V. In this case, you want the control sequence name obtained from \name and the replacement text obtained from the definition of \value, so what you really need is \cslet{\name}{\value}, which creates a new command formed from the definition of \name and assigns it to the definition of \value (so it retains the correct definition after \value is redefined in the next iteration of the loop).

A couple of notes: \value is already defined by the LaTeX kernel (it obtains the value of a counter), so its better to use another command name (say, \Value) to avoid breaking anything. You also need to trim the spurious space from the data.

Updated MWE:

\documentclass{scrartcl}

\usepackage{filecontents}

\begin{filecontents*}{Unnamed1.csv}
name,value
Voltage,14 V
Current,1 A
MoreText,something more is written here
Date,2017/03/08
\end{filecontents*}

\usepackage[ngerman]{babel}
\usepackage{datatool}
\DTLsetseparator{,}
\DTLloaddb{Test}{Unnamed1.csv}
\begin{document}

\DTLforeach{Test}{\Name=name,\Value=value}
{%
 \cslet{\Name}{\Value}%
}

Voltage: \Voltage.

Current: \Current.

MoreText: \MoreText.

Date: \Date.

\end{document}

Voltage: 14 V. Current: 1 A. MoreText: something more is written here. Date: 2017/03/08.

  • Hello Nicola, thanks for your answer! Exactly, i want a command whose Name is read from the first row and define the value of the second row to that. Unfortunately i have around 50 rows not only 2. ist just a list with lots of info like: t1 = 50 K, U1 = 12 V etc. – Jonas Mar 8 '17 at 14:03
  • @Jonas Could you add a few sample rows (say, 4 rows) to your question to illustrate it. – Nicola Talbot Mar 8 '17 at 14:14
  • i added it to the original question, thank you! – Jonas Mar 8 '17 at 14:24
  • Hello @Nicola Talbot, i am reading multiple files. I tried to add a Counter to the \Name so everything is unique, but i can't get it to work. My code: \cslet{\expandafter\csname\Name\arabic{somecounter}\endcsname}{\Value} – Jonas Apr 26 '17 at 9:36
  • @Jonas What do you actually want the new command to be called? Suppose \Name is Voltage and somecounter has the value 1, then your code tries to create a control sequence whose name is given by \csname Voltage1\endcsname so you're actually trying to create \csname \csname Voltage1\endcsname\endcsname. Did you intend \cslet{\Name\arabic{somecounter}}{\Value} instead? Which would create the command whose name is Voltage1 that needs to be accessed using \csuse{Voltage1}. (\Voltage1 would be treated as two tokens \Voltage followed by 1.) – Nicola Talbot Apr 26 '17 at 10:03
4

Is something like this, with the readarray package, sufficient?

REVISION

\documentclass{article}
\usepackage{readarray}[2016-11-07]
\usepackage{filecontents}
\begin{filecontents*}{myfile.dat}
First, Last, Birthday 
John, Doe, 01/01/68 
\end{filecontents*}
\newcounter{mycount}
\newcommand\assigndat[1]{%
  \readarraysepchar{,}%
  \readdef{#1}\mydata%
  \readarray*\mydata\myarray[-,\ncols]%
  \setcounter{mycount}{0}%
  \whiledo{\themycount<\ncols}{%
    \stepcounter{mycount}%
    \edef\tmp{\myarray[1,\themycount]}%
    \expandafter\expandafter\expandafter\xdef\expandafter\csname\tmp\endcsname{%
      \myarray[2,\themycount]}%
    }%
}
\begin{document}
\assigndat{myfile.dat}
\First

\Last

\Birthday
\end{document}

enter image description here


ORIGINAL ANSWER

\documentclass{article}
\usepackage{readarray}[2016-11-07]
\usepackage{filecontents}
\begin{filecontents*}{myfile}
First, Last, Birthday 
John, Doe, 01/01/68 
\end{filecontents*}
\newcommand\assigndat[1]{%
  \edef\tmp{\myarray[1,#1]}
  \expandafter\expandafter\expandafter\def\expandafter\csname\tmp\endcsname{\myarray[2,#1]}
}
\begin{document}
\readarraysepchar{,}
\readdef{myfile.tex}\mydata
\readarray*\mydata\myarray[-,\ncols]
Column 3 title is ``\myarray[1,3]''.

Column 3 data is ``\myarray[2,3]''

\assigndat{1}\First

\assigndat{2}\Last

\assigndat{3}\Birthday
\end{document}

enter image description here

  • Thanks for your quick answer! Unfortunately i don't want to "hard code" the items of my list. There is a 100% chance, that there are changes made in the future and by defining variables inside the document it would not matter where the data is written as long as the name is not changed. – Jonas Mar 8 '17 at 12:56
  • @Jonas Please see my revision, if this is more in line with your desires. – Steven B. Segletes Mar 8 '17 at 13:06
  • Hello! It doesnt compile on my System. i get an undefined control sequence for \assigndat. I'll try to understand why tomorrow. Thanks a lot for your help! – Jonas Mar 8 '17 at 14:08
  • @Jonas Make sure you copied the text properly from my answer. Clearly, you can see \assigndat defined in the preamble. Thus, it should be defined when you invoke it in the document. – Steven B. Segletes Mar 8 '17 at 14:10
  • @Jonas also make sure your version of readarray is up to date. – Steven B. Segletes Mar 8 '17 at 14:53

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.