8

I am going to create a number of letters by using the datatool package to import data from external files. Everything works smoothly except getting the company names correct as these may contain special characters, e.g. ampersand "&". Thus, I import the company name, e.g. "Father & Sons" and store it in a string variable to be used later in my document.

My question is does there exist a method to suppress the interpretation of the "&" and other special characters? I have tried using verbatim and alltt without good results. Alternatively I could replace the &s in my external file but I would rather get a generic solution that just writes the imported text as it is.

The example below is simplified but illustrates the problem:

\documentclass[10pt]{article}
\usepackage[a4paper]{geometry}

\newcommand{\txtstring}{Father & Sons}
\newcommand{\txtstringtwo}{Father \& Sons}

\begin{document}

\txtstring
\par
\txtstringtwo

\end{document}

The error I get is "Misplaced alignment tab character &. \txtstring", which is due to the "&". Hence, can I resolve the string variable without interpreting the "&"?


The solution with using "\detokenize" suggested by Henri Menke (and Ulrike Fischer) solves the problem. I have added a "real" example using the datatool package as suggested by egreg.

\documentclass[10pt]{article}

%%% Definer papiropsætning og margin %%%%%%%%%%%%%%%%%%%%%%%
\usepackage[a4paper]{geometry}
\usepackage{datatool}     % access .csv
\usepackage[absolute]{textpos}
\usepackage{lipsum}


%%% Definer ingen paragraf indent  %%%%%%%%%%%%%%%%%%%%%%%%%
\setlength{\parindent}{0pt}

\newcommand{\txtstring}{Father & Sons}
\newcommand{\txtstringtwo}{Father \& Sons}


%%% Define database load (CSV) %%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%\DTLsetseparator{;}       % use semi-colon as delimter (commas use in quotations)
%\DTLloaddb[noheader,keys={CVR,CompanyName,LastName,FirstName,Address,PostCode,City}]{data}{test2.csv}
%\DTLloaddb[noheader,keys={CVR,CPR,DatoStart,DatoSlut}]{data_detail}{test_detail.csv}


%%% Here I create a database %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\DTLnewdb{testdata}
\DTLnewrow{testdata}%
\DTLnewdbentry{testdata}{CVR}{12 23 45 56}%
\DTLnewdbentry{testdata}{CompanyName}{Fox & Sons}%
\DTLnewdbentry{testdata}{LastName}{Fox}%
\DTLnewdbentry{testdata}{FirstName}{Red}%
\DTLnewdbentry{testdata}{Address}{Fowl Street 1}%
\DTLnewdbentry{testdata}{PostCode}{4567}%
\DTLnewdbentry{testdata}{City}{Fox Town}%
\DTLnewrow{testdata}%
\DTLnewdbentry{testdata}{CVR}{45 56 67 78}%
\DTLnewdbentry{testdata}{CompanyName}{Elephant & Daughters}%
\DTLnewdbentry{testdata}{LastName}{Fant}%
\DTLnewdbentry{testdata}{FirstName}{Eli}%
\DTLnewdbentry{testdata}{Address}{Africa Road 1}%
\DTLnewdbentry{testdata}{PostCode}{1259}%
\DTLnewdbentry{testdata}{City}{Mega City}%


\begin{document}

%%% Here I read from databse an create one letter per line %
\DTLforeach{testdata}{%
    \CV=CVR,%
    \CN=CompanyName,%
    \LN=LastName,%
    \FN=FirstName,%
    \AD=Address,%
    \PC=PostCode,%
    \CT=City%
}{%


%%% Write sender %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\begin{textblock*}{\textwidth}[0,0](25mm,37mm)
    \scriptsize%
    \textbf{Afs: SomeStreet 1, 1234 City}
\end{textblock*}


%%% Write recipient %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\begin{textblock*}{\textwidth}[0,0](25mm,42mm)
    \detokenize\expandafter{\CN}\\
    \detokenize\expandafter{\FN}~\detokenize\expandafter{\LN}\\%
    \detokenize\expandafter{\AD}\\%
    \detokenize\expandafter{\PC}~\detokenize\expandafter{\CT}%
\end{textblock*}


%%% Write heading %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\begin{textblock*}{\textwidth}[0,0](20mm,98mm)
\textbf{\Large Here is my header}\\

\lipsum[4]

\end{textblock*}

\null\clearpage

}

\end{document}
6
  • \newcommand{\txtstring}{\detokenize{Father & Sons}}? Jun 10, 2016 at 7:09
  • 1
    alternatively: \detokenize\expandafter{\txtstring} Jun 10, 2016 at 7:10
  • A small example of an import might help more than this generic situation. Maybe some feature of datatool can be used.
    – egreg
    Jun 10, 2016 at 8:25
  • 1
    If you're planning on loading the data from a CSV file, then you just need to use \DTLloadrawdb instead of \DTLloaddb. That will convert any & to \&. Jun 10, 2016 at 10:53
  • 2
    The code is simpler with \DTLloadrawdb. It makes the substitutions as the data is loaded, so you don't need all the \detokenize\expandafter every time you access the data. Jun 10, 2016 at 12:04

2 Answers 2

4

Here's a solution that just uses \DTLloadrawdb instead of \DTLloaddb:

\documentclass{article}

\usepackage{filecontents}
\usepackage{datatool}

\begin{filecontents*}{test.csv}
CVR,CompanyName,LastName,FirstName,Address,PostCode,City
12 23 45 56,Fox & Sons,Fox,Red,Fowl Street 1,4567,Fox Town
45 56 67 78,Elephant & Daughters,Fant,Eli,Africa Road 1,1259,Mega City
\end{filecontents*}

\DTLloadrawdb{testdata}{test.csv}
\begin{document}
\DTLforeach{testdata}%
{%
    \CV=CVR,%
    \CN=CompanyName,%
    \LN=LastName,%
    \FN=FirstName,%
    \AD=Address,%
    \PC=PostCode,%
    \CT=City%
}%
{%
  \CV, \CN, \LN, \FN, \AD, \PC, \CT\par
}
\end{document}

The ampersands are automatically converted to \& when the data is read from the CSV file. Nothing special needs to be done in the \DTLforeach loop. The above example produces:

image of document

Similarly for eight of the other special characters. The only special character not to be mapped is the backslash. You can also add your own mappings (before \DTLloadrawdb). For example:

\DTLrawmap{£}{\pounds}
9

You can set locally the catcode of & when reading the data. It will not disturb the use of & later, and unlike \detokenize it will not break other commands like non-ascii input in your input:

    \documentclass[10pt]{article}
    \usepackage[T1]{fontenc}
    \usepackage[utf8]{inputenc}
    \usepackage[a4paper]{geometry}

    \catcode`\&=12
    \newcommand{\txtstring}{Father & Sons & Mütter}
    \newcommand{\txtstringtwo}{Father \& Sons & Mütter}
    \newcommand{\txtstringthree}{\detokenize{Father & Sons & Mütter}}
    \catcode`\&=4

    \begin{document}

    \txtstring: OK
    \par
    \txtstringtwo: OK
    \par
    \txtstringthree: Bad

    \begin{tabular}{ll}
    blub & bla
    \end{tabular}
    \end{document}

enter image description here

3
  • Hmm, that broke ü it seems
    – daleif
    Jun 10, 2016 at 7:58
  • 1
    @daleif Which proves Ulrike's statement
    – egreg
    Jun 10, 2016 at 8:05
  • 1
    @daleif: I hope it is clearer now ... Jun 10, 2016 at 8:20

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .