
Ich werde eine Reihe von Briefen erstellen, indem ich das Datatool-Paket verwende, um Daten aus externen Dateien zu importieren. Alles funktioniert reibungslos, außer dass die Firmennamen korrekt sein müssen, da diese Sonderzeichen enthalten können, z. B. das Et-Zeichen „&“. Daher importiere ich den Firmennamen, z. B. „Vater & Söhne“, und speichere ihn in einer Zeichenfolgenvariable, um ihn später in meinem Dokument zu verwenden.
Meine Frage ist, ob es eine Methode gibt, die Interpretation des „&“ und anderer Sonderzeichen zu unterdrücken. Ich habe es mit und versucht, verbatim
aber alltt
ohne gute Ergebnisse. Alternativ könnte ich das s in meiner externen Datei ersetzen, &
aber ich würde lieber eine generische Lösung bekommen, die den importierten Text einfach so schreibt, wie er ist.
Das folgende Beispiel ist vereinfacht, veranschaulicht aber das Problem:
\documentclass[10pt]{article}
\usepackage[a4paper]{geometry}
\newcommand{\txtstring}{Father & Sons}
\newcommand{\txtstringtwo}{Father \& Sons}
\begin{document}
\txtstring
\par
\txtstringtwo
\end{document}
Der Fehler, den ich erhalte, ist „Falsch platziertes Ausrichtungstabierzeichen &. \txtstring“, was auf das „&“ zurückzuführen ist. Kann ich daher die Zeichenfolgenvariable auflösen, ohne das „&“ zu interpretieren?
Die von Henri Menke (und Ulrike Fischer) vorgeschlagene Lösung mit „\detokenize“ behebt das Problem. Ich habe ein „echtes“ Beispiel mit dem Datatool-Paket hinzugefügt, wie von egreg vorgeschlagen.
\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}
Antwort1
Hier ist eine Lösung, die einfach \DTLloadrawdb
anstelle von verwendet \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}
\&
Die Et-Zeichen werden beim Lesen der Daten aus der CSV-Datei automatisch in umgewandelt . In der \DTLforeach
Schleife muss nichts Besonderes getan werden. Das obige Beispiel ergibt:
Gleiches gilt für acht der anderen Sonderzeichen. Das einzige Sonderzeichen, das nicht zugeordnet werden muss, ist der Backslash. Sie können auch Ihre eigenen Zuordnungen hinzufügen (vor \DTLloadrawdb
). Beispiel:
\DTLrawmap{£}{\pounds}
Antwort2
Sie können den Catcode von & beim Lesen der Daten lokal festlegen. Dies stört die spätere Verwendung von & nicht und im Gegensatz zu \detokenize wird es andere Befehle wie Nicht-ASCII-Eingaben in Ihrer Eingabe nicht beschädigen:
\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}