Verwenden von \ DTLfetch in einem \ href

Dec 04 2020

Ich versuche, in LaTeX einen neuen Befehl zu erstellen, der eine Google Map-URL erstellt, die auf die Koordinaten verweist, die dem im aufgerufenen Befehl als Parameter angegebenen Ort zugeordnet sind (eine Art "Tabellensuchfunktion"). Die Orte und die relativen Koordinaten werden in einer coords.CSVDatei gespeichert und müssen mit dem datatoolPaket gelesen werden .

Die Google Map-URL sollte wie folgt aufgebaut sein:

https://www.google.com/maps/?q=<LAT>,<LNG>

Wo <LAT>und <LNG>werden die Längen- und Breitengradkoordinaten aus der coords.CSVDatei geladen , die folgendermaßen strukturiert ist:

Place,LAT,LNG
Test,42.0000,42.0000
...

So wurde der Befehl definiert:

\usepackage{datatool}
\newcommand{\coords}[1]{
    % Loads the CSV
    \DTLsetseparator{,}
    \DTLloaddb{coords}{doc/coords.csv}
        
    % Assigns the coordinates to the variables \LAT and \LNG, relative to specific place (the parameter #1)
    \def \LAT {\DTLfetch{coords}{Place}{#1}{LAT}}
    \def \LNG {\DTLfetch{coords}{Place}{#1}{LNG}}
    
    % Generates the URL pointing to Google Maps
    Place: \href{https://www.google.com/maps/?q=\LNG ,\LNG}{#1}
}

Schließlich benutze ich den neuen Befehl folgendermaßen:

\coords{Test}

Ich habe es geschafft, die Koordinaten des im Befehl aufgerufenen Ortes korrekt zu laden (in diesem Fall "Test"), aber wenn ich versuche, die URL zu generieren, gibt mir LaTeX viele Fehler, von denen die meisten sind ! Undefined control sequence. Wenn ich \LATund \LNGaus der Zeile, in der die URL generiert wird (innerhalb der Befehlsdefinition), entferne , wird keine Fehlermeldung angezeigt, aber die URL enthält natürlich keine Koordinaten, da sie in den Variablen \LATund gespeichert sind \LNG.

Gibt es eine Möglichkeit, die URL mithilfe der im \hrefBefehl definierten Variablen ordnungsgemäß zu generieren ?

Dies ist ein Testbeispiel:

\documentclass[a4paper,10pt]{article}

\usepackage{hyperref}           
\usepackage{datatool}

\newcommand{\coords}[1]{
     % Loads the CSV
    \DTLsetseparator{,}
    \DTLloaddb{coords}{coords.csv}
        
    % Assigns the coordinates to the variables \LAT and \LNG, relative to specific place (the parameter #1)
    \def \LAT {\DTLfetch{coords}{Place}{#1}{LAT}}
    \def \LNG {\DTLfetch{coords}{Place}{#1}{LNG}}
    
    % Generates the URL pointing to Google Maps
    Place: \href{https://www.google.com/maps/?q=\LAT ,\LNG}{#1}
}

\begin{document}

\coords{Test}

\end{document}

Antworten

4 egreg Dec 04 2020 at 11:05

Sie können den gleichen Trick wie in meiner Antwort zum Abrufen der Teilzeichenfolge von \ DTLfetch verwenden

\begin{filecontents*}{\jobname.csv}
Place,LAT,LNG
Test,42.0000,42.0000
\end{filecontents*}

\documentclass{article}
\usepackage{datatool}
\usepackage{hyperref}

\DTLsetseparator{,}
\DTLloaddb{coords}{\jobname.csv}

\newcommand{\DTLfetchsave}[5]{% see https://tex.stackexchange.com/a/335489/4427
  \edtlgetrowforvalue{#2}{\dtlcolumnindex{#2}{#3}}{#4}%
  \dtlgetentryfromcurrentrow{\dtlcurrentvalue}{\dtlcolumnindex{#2}{#5}}%
  \let#1\dtlcurrentvalue
}

\newcommand{\coords}[1]{%
  \DTLfetchsave{\LAT}{coords}{Place}{#1}{LAT}%
  \DTLfetchsave{\LNG}{coords}{Place}{#1}{LNG}%
  % Generates the URL pointing to Google Maps
  Place: \href{https://www.google.com/maps/?q=\LAT,\LNG}{#1}%
}

\begin{document}

\coords{Test}

\end{document}

Früher habe ich es \jobnamevermieden, meine Dateien zu überladen. Sie können einen beliebigen Dateinamen für die Datenbank verwenden.

Laden Sie die Datenbank einmal und nicht jedes Mal, wenn Sie anrufen \coords.

3 UlrichDiez Dec 04 2020 at 12:34

Ich schlage folgenden Ansatz vor:

\documentclass[a4paper,10pt]{article}

% Let's create the file coords.csv - the directory ./doc  must exist 
% and writing-permission for that directory must be given!!!
% An already existing file won't be overwritten by the 
% filecontents*-environment (unless you provide the "overwrite"-option)
% and you will be informed about the fact that the file already
% exists via a message in the .log-file only. You won't get a 
% message on the terminal/console.
\begin{filecontents*}{doc/coords.csv}
Place,LAT,LNG
Test,42.0000,42.0000
\end{filecontents*}

\usepackage{hyperref}           
\usepackage{datatool}

\newcommand{\coords}[1]{%%%
    \begingroup
    % Load the CSV only if database "coords" doesn't already exist:
    \DTLifdbexists{coords}{}{%%%
      %\DTLsetseparator{,}% Comma is the default, so this probably is not needed.
      \DTLloaddb{coords}{doc/coords.csv}%%%
    }%%%
    % Assign the coordinates of the place whose name is denoted by the
    % parameter #1 to the macros \LAT and \LNG:
    \edtlgetrowforvalue{coords}{\dtlcolumnindex{coords}{Place}}{#1}%%%
    \dtlgetentryfromcurrentrow{\LAT}{\dtlcolumnindex{coords}{LAT}}%%%
    \dtlgetentryfromcurrentrow{\LNG}{\dtlcolumnindex{coords}{LNG}}%%%
    %%%
    % Use the name (denoted by #1) of the place as a hyperlink leading
    % to the corresponding URL of Google Maps:
    Place: \href{https://www.google.com/maps/?q=\LAT,\LNG}{#1}%%%
    \endgroup
}%%%

\begin{document}

\coords{Test}

\end{document}

Ich schlage diesen Ansatz vor, da bei Ihrem Code einige Probleme auftreten:

Fehler 1:

Ihr \coords-Befehl erzeugt unerwünschte Space-Token und \par-Token:

Ich schreibe es mit Kommentaren neu, die angeben, wo diese unerwünschten Token entstehen:

\newcommand{\coords}[1]{ %<- unwanted space-token yields horizontal space in horizontal mode
    % Loads the CSV
    \DTLsetseparator{,} %<- unwanted space-token yields horizontal space in horizontal mode
    \DTLloaddb{coords}{doc/coords.csv} %<- unwanted space-token yields horizontal space in horizontal mode
        %<- unwanted control word token \par
    % Assigns the coordinates to the variables \LAT and \LNG, relative to specific place (the parameter #1)
    \def \LAT {\DTLfetch{coords}{Place}{#1}{LAT}} %<- unwanted space-token yields horizontal space in horizontal mode
    \def \LNG {\DTLfetch{coords}{Place}{#1}{LNG}} %<- unwanted space-token yields horizontal space in horizontal mode
        %<- unwanted control word token \par                
    % Generates the URL pointing to Google Maps
    Place: \href{https://www.google.com/maps/?q=\LAT ,\LNG}{#1} %<- unwanted space-token yields horizontal space in horizontal mode
}

Ausgabe 2:

Das Hyperref-Handbuch besagt, dass Token im URL-Argument von \hrefvollständig erweiterbar sein müssen.

Ihre Befehle \LATund \LNGsind nicht vollständig erweiterbar, da ihre Definition \DTLfetchdas Steuerwort- Token enthält, während das Handbuch des datatool-Pakets dies eindeutig angibt

\DTLfetch{students}{regnum}{\RegNum}{forename}
entspricht

\dtlgetrowforvalue{students}{\dtlcolumnindex{students}{regnum}}{\RegNum}%

\dtlgetentryfromcurrentrow{\dtlcurrentvalue}{\dtlcolumnindex{students}{forename}}% \dtlcurrentvalue

Dies zeigt an, dass \DTLfetch(und damit jedes Makro, dessen Erweiterung zu einem bestimmten Zeitpunkt das Token ergibt \DTLfetch) nicht vollständig erweiterbar ist, wenn ein Makro \dtlcurrentvaluedurch definiert wird \dtlgetentryfromcurrentrow.

Problem 3:

Ich bezweifle, dass es notwendig ist, die Datenbank bei jedem Aufruf von zu laden \coords.

Ausgabe 4:

Mit dem Befehl \DTLsetseparatorsetzen Sie das Trennzeichen für Einträge einer Datenbank auf Komma, obwohl dies die Standardeinstellung ist. Das ist also wahrscheinlich veraltet.