# definition variables inserted as datatool arguments

I'd like to create tikzpicture (animated in fact) that would read numbers from text file and use them either as coordinates or nodes or for further calculations. It seems that datatool package would be suitable, but I can only make it work if I pass the arguments directly, as in MWE:

\documentclass{standalone}
\usepackage{filecontents}
\usepackage{tikz}
\usetikzlibrary{calc}
\usepackage{datatool}
\usepackage{animate}
\begin{filecontents*}{test.csv}
f wzb em
380 5 3
400 1 2
405 2 5
410 43 5656
415 4   94
420 4 6
\end{filecontents*}
\DTLsetseparator{ }
\begin{document}

\begin{animateinline}[label=graph_switch,controls=step]{1}
\multiframe{5}{iFrame=400+5}{
\begin{tikzpicture}
\useasboundingbox[draw] (-3,-2) rectangle (5,6);
\pgfmathparse{1000/\iFrame}
\edef\dlugosc{\pgfmathresult}
\DTLassignfirstmatch{widmo}{f}{405}{\wzb=wzb,\em=em}
%\DTLassignfirstmatch{widmo}{f}{\dlugosc}{\wzb=wzb,\em=em}
%\DTLassignfirstmatch{widmo}{f}{\iFrame}{\wzb=wzb,\em=em}
\draw[->] (0,0) --  (\wzb, \em) --(\dlugosc:1) node[left] {\dlugosc};
\node at (2,0) {em=\em, wzb=\wzb};
\end{tikzpicture}
}
\end{animateinline}
\end{document}


The two commented lines don't work as I with they would. Is there a simple way to fix it or other package that would allow me to look through the text file, pick value from specific line and use is as a variable? I'd appreciate any suggestions on that.

• You should be able to do it as \def\tmp{\DTLassignfirstmatch{widmo}{f}} \expandafter\tmp\expandafter{\iFrame}{\wzb=wzb,\em=em}. However, there appears to be other things wrong with your MWE, and I don't know enough about datatool to assist. – Steven B. Segletes Mar 24 '20 at 11:53
• Yes, this works! Thank you very much. – Malgorzata Mar 24 '20 at 14:49

In general, when you are confronted with a macro invocation such as

\DTLassignfirstmatch{widmo}{f}{\iFrame}{\wzb=wzb,\em=em}


in which the macro seems to demand actual data, rather than \iFrame reference to data, you need to expand the command holding the data, in this case \iFrame.

If you are lucky, \iFrame will contain the actual tokens of the data, and will only require a single expansion to obtain them. If you are unlucky, the \iFrame macro will not be expandable at all, in which case what I describe will not solve your problem. Somewhere in between these extremes, \iFrame may require a finite number of expansions to produce the desired tokens of data (I will not describe how to accomplish that here, but there are ways to do so).

Fortunately, in our case, \iFrame contains the actual tokens of data, so a single expansion only is required. A typical method for achieving this is as follows

\def\tmp{\DTLassignfirstmatch{widmo}{f}}
\expandafter\tmp\expandafter{\iFrame}{\wzb=wzb,\em=em}


Here, we store a brace-balanced expression leading up to \iFrame in a temporary macro \tmp. Then, one can use \expandafter to expand \iFrame before expanding \tmp. Thus, by the time \DTLassignfirstmatch is executed, the occurrence of \iFrame has already been expanded to the actual data tokens that are required of the \DTL... macro.

The documentation of datatool is clear about it:

\DTLassignfirstmatch{⟨db name⟩}{⟨col key⟩}{⟨value⟩}{⟨assign list⟩}

This is similar to \DTLassign except that it applies to the first row in the given database where the column identified by the label ⟨col key⟩ has the given value. Note that no expansion is performed in the match. The value must be an exact match.

On the other hand, immediately after this description you find

\xDTLassignfirstmatch{⟨db name⟩}{⟨col key⟩}{⟨value⟩}{⟨assign list⟩}

This is like \DTLassignfirstmatch but performs a one-level expansion on ⟨value⟩.

So you want to use

\xDTLassignfirstmatch{widmo}{f}{\iFrame}{\wzb=wzb,\em=em}


If I try, I get “dimension too large”, though.

Anyway, if I test it with

\def\iFrame{405}

\xDTLassignfirstmatch{widmo}{f}{\iFrame}{\wzb=wzb,\em=em}

\verb|\wzb| = \wzb

\verb|\em| = \em


I get

• Thank you for your elaboration. It helped a lot! – Malgorzata Mar 25 '20 at 18:55