Usando \ DTLfetch dentro de un \ href
Estoy tratando de crear un nuevo comando en LaTeX que crea una URL de Google Map apuntando a las coordenadas asociadas con el lugar especificado como parámetro en el comando llamado (una especie de función de "búsqueda de tabla"). Los lugares y las coordenadas relativas se almacenan dentro de un coords.CSV
archivo y deben leerse usando el datatool
paquete.
La URL del mapa de Google debe estructurarse así:
https://www.google.com/maps/?q=<LAT>,<LNG>
donde <LAT>
y <LNG>
son las coordenadas de latitud y longitud cargadas desde el coords.CSV
archivo, que está estructurado de esta manera:
Place,LAT,LNG
Test,42.0000,42.0000
...
Así es como se definió el comando:
\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}
}
Finalmente, uso el nuevo comando de esta manera:
\coords{Test}
He logrado cargar correctamente las coordenadas del lugar llamado dentro del comando (en este caso "Test"), pero cuando intento generar la URL, LaTeX me da muchos errores, la mayoría de los cuales son ! Undefined control sequence
. Si elimino \LAT
y \LNG
de la línea donde se genera la URL (dentro de la definición del comando), no obtengo ningún error, pero por supuesto la URL no contiene coordenadas, ya que están almacenadas dentro de las variables \LAT
y \LNG
.
¿Hay alguna forma de generar correctamente la URL utilizando las variables definidas dentro del \href
comando?
Este es un ejemplo de prueba:
\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}
Respuestas
Puede usar el mismo truco que en mi respuesta para recuperar la subcadena 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}
Solía \jobname
evitar golpear mis archivos. Puede utilizar el nombre de archivo que desee para la base de datos.
Cargue la base de datos una vez, no cada vez que llame \coords
.
Sugiero el siguiente enfoque:
\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}
Sugiero este enfoque porque con su código hay algunos problemas:
Problema 1:
Su \coords
-comando produce tokens de espacio y tokens no \par
deseados:
Lo reescribo con comentarios que indican dónde surgen estos tokens no deseados:
\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
}
Problema 2:
El hiperref-manual dice que los tokens en el argumento URL de \href
deben ser completamente expandibles.
Sus comandos \LAT
y \LNG
no son completamente expandibles porque su definición contiene el token de la palabra de control \DTLfetch
mientras que el manual del paquete datatool dice claramente que
\DTLfetch{students}{regnum}{\RegNum}{forename}
es igual a
lo que indica que\dtlgetrowforvalue{students}{\dtlcolumnindex{students}{regnum}}{\RegNum}%
\dtlgetentryfromcurrentrow{\dtlcurrentvalue}{\dtlcolumnindex{students}{forename}}% \dtlcurrentvalue
\DTLfetch
(y por lo tanto, cada macro cuya expansión en alguna etapa produce el token
\DTLfetch
) no es completamente expandible cuando una macro
\dtlcurrentvalue
se define por
\dtlgetentryfromcurrentrow
.
Problema 3:
Dudo que sea necesario cargar la base de datos con cada llamada a \coords
.
Problema 4:
Utilice el comando \DTLsetseparator
para establecer el separador de las entradas de una base de datos en coma, aunque este es el valor predeterminado. Entonces esto probablemente esté obsoleto.