5

In the following example \DTLgetvalueforkey retrieves the information without problem, while \DTLfetch fails:

\documentclass{article}

\usepackage{filecontents}
\begin{filecontents*}{data.csv}
Heading A, Heading B, Heading C
One,    Een,  1
Two,    Twee, 2
T_hree, Drie, 3
Four,   Vier, 4
\end{filecontents*}

\usepackage{datatool}

\begin{document}

\DTLloadrawdb
  [keys={HeadA,HeadB,HeadC}]
  {data}{data.csv}

\DTLdisplaydb{data}

\bigskip

% \DTLgetvalueforkey{<cmd>}{<key>}{<db name>}{<ref key>}{<ref value>}
% \DTLfetch{<db name>}{<col1 name>}{<col1 value>}{<col2 name>}

\textbf{Heading A} = `Two' corresponds to \textbf{Heading B} =
\DTLgetvalueforkey{\datavalue}{HeadB}{data}{HeadA}{Two}\datavalue% Twee

\textbf{Heading A} = `Two' corresponds to \textbf{Heading B} =
\DTLfetch{data}{HeadA}{Two}{HeadB}% Twee

\textbf{Heading A} = `T\_hree' corresponds to \textbf{Heading B} =
\DTLgetvalueforkey{\datavalue}{HeadB}{data}{HeadA}{T\_hree}\datavalue% Drie

% Should be the same as above, but not found
\textbf{Heading A} = `T\_hree' corresponds to \textbf{Heading B} =
\DTLfetch{data}{HeadA}{T\_hree}{HeadB}% Drie

\end{document}

Why is this? Can \DTLfetch be fixed to work here?

The problem is specific to the use of _ inside CSV entries. The input I'm working with contains this, so there's very little I can do to remove it.

6

The datatool user guide mentions the following about \DTLfetch:

\DTLfetch{<db name>}{<col1 name>}{<col1 value>}{<col2 name>}

This fetches and displays the value for <col2 name> in the first row where the value of <col1 name> is <col1 value>. (Note that all arguments are expanded.)

Expansion here is causing the issue. To get around this, fetch for T\noexpand\_hree rather than T\_hree:

enter image description here

\documentclass{article}

\usepackage{filecontents}
\begin{filecontents*}{data.csv}
Heading A, Heading B, Heading C
One,    Een,  1
Two,    Twee, 2
T_hree, Drie, 3
Four,   Vier, 4
\end{filecontents*}

\usepackage{datatool}

\begin{document}

\DTLloadrawdb
  [keys={HeadA,HeadB,HeadC}]
  {data}{data.csv}

\DTLdisplaydb{data}

\bigskip

% \DTLgetvalueforkey{<cmd>}{<key>}{<db name>}{<ref key>}{<ref value>}
% \DTLfetch{<db name>}{<col1 name>}{<col1 value>}{<col2 name>}

\textbf{Heading A} = `Two' corresponds to \textbf{Heading B} =
\DTLgetvalueforkey{\datavalue}{HeadB}{data}{HeadA}{Two}\datavalue% Twee

\textbf{Heading A} = `Two' corresponds to \textbf{Heading B} =
\DTLfetch{data}{HeadA}{Two}{HeadB}% Twee

\textbf{Heading A} = `T\_hree' corresponds to \textbf{Heading B} =
\DTLgetvalueforkey{\datavalue}{HeadB}{data}{HeadA}{T\_hree}\datavalue% Drie

\textbf{Heading A} = `T\_hree' corresponds to \textbf{Heading B} =
\DTLfetch{data}{HeadA}{T\noexpand\_hree}{HeadB}% Drie

\end{document}

If you are searching based on content within a macro, as in

\def\Three{T\_hree}
\DTLfetch{data}{HeadA}{\Three}{HeadB}% Drie

you will still have a problem. Here you still need to avoid the expansion of \_. You can do this using grouping a \letting \_ to \relax:

\def\Three{T\_hree}
{\let\_\relax
\DTLfetch{data}{HeadA}{\Three}{HeadB}}% Drie

Other options include making \_ robust (via etoolbox with \robustify{\_}, say).

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.