Utiliser \ DTLfetch dans un \ href
J'essaie de créer une nouvelle commande dans LaTeX qui crée une URL Google Map pointant vers les coordonnées associées à l'endroit spécifié comme paramètre dans la commande appelée (une sorte de fonction de «recherche de table»). Les lieux et les coordonnées relatives sont stockés dans un coords.CSV
fichier et doivent être lus à l'aide du datatool
package.
L'URL de Google Map doit être structurée comme celle-ci:
https://www.google.com/maps/?q=<LAT>,<LNG>
où <LAT>
et <LNG>
sont les coordonnées de latitude et de longitude chargées à partir du coords.CSV
fichier, qui est structuré de cette manière:
Place,LAT,LNG
Test,42.0000,42.0000
...
Voici comment la commande a été définie:
\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}
}
Enfin, j'utilise la nouvelle commande de cette manière:
\coords{Test}
J'ai réussi à charger correctement les coordonnées de l'endroit appelé à l'intérieur de la commande (dans ce cas "Test"), mais quand j'essaye de générer l'URL, LaTeX me donne beaucoup d'erreurs, dont la plupart le sont ! Undefined control sequence
. Si je supprime \LAT
et \LNG
de la ligne où l'URL est générée (dans la définition de la commande), je n'obtiens aucune erreur, mais bien sûr l'URL ne contient aucune coordonnée, car elles sont stockées dans les variables \LAT
et \LNG
.
Existe-t-il un moyen de générer correctement l'URL en utilisant les variables définies dans la \href
commande?
Ceci est un exemple de test:
\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}
Réponses
Vous pouvez utiliser la même astuce que dans ma réponse pour récupérer la sous-chaîne de `\ DTLfetch`
\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}
J'avais l'habitude \jobname
d'éviter de clobber mes fichiers. Vous pouvez utiliser le nom de fichier de votre choix pour la base de données.
Chargez la base de données une fois, pas à chaque appel \coords
.
Je suggère l'approche suivante:
\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}
Je suggère cette approche car avec votre code, il y a quelques problèmes:
Problème 1:
Votre \coords
-commande produit des jetons d'espace et des jetons \par
indésirables:
Je le réécris avec des commentaires indiquant d'où viennent ces jetons indésirables:
\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
}
Problème 2:
Le manuel hyperref dit que les jetons dans l'argument URL de \href
doivent être entièrement extensibles.
Vos commandes \LAT
et \LNG
ne sont pas entièrement extensibles car leur définition contient le jeton de mot de contrôle \DTLfetch
alors que le manuel du datatool-package dit clairement que
\DTLfetch{students}{regnum}{\RegNum}{forename}
est égal à
ce qui indique que\dtlgetrowforvalue{students}{\dtlcolumnindex{students}{regnum}}{\RegNum}%
\dtlgetentryfromcurrentrow{\dtlcurrentvalue}{\dtlcolumnindex{students}{forename}}% \dtlcurrentvalue
\DTLfetch
(et donc chaque macro dont l'expansion à un certain stade produit le jeton
\DTLfetch
) n'est pas entièrement extensible car une macro
\dtlcurrentvalue
est définie par
\dtlgetentryfromcurrentrow
.
Problème 3:
Je doute qu'il soit nécessaire de charger la base de données à chaque appel à \coords
.
Problème 4:
Vous utilisez la commande \DTLsetseparator
pour définir le séparateur des entrées d'une base de données sur une virgule bien qu'il s'agisse de la valeur par défaut. Donc, c'est probablement obsolète.