Usando \ DTLfetch dentro de um \ href
Estou tentando criar um novo comando em LaTeX que cria um URL do Google Map apontando para as coordenadas associadas ao local especificado como um parâmetro no comando chamado (uma espécie de função de "pesquisa de tabela"). Os lugares e as coordenadas relativas são armazenados dentro de um coords.CSV
arquivo e devem ser lidos usando o datatool
pacote.
O URL do Google Maps deve ser estruturado como este:
https://www.google.com/maps/?q=<LAT>,<LNG>
onde <LAT>
e <LNG>
são as coordenadas de latitude e longitude carregadas do coords.CSV
arquivo, que é estruturado desta forma:
Place,LAT,LNG
Test,42.0000,42.0000
...
É assim que o comando foi definido:
\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}
}
Por fim, uso o novo comando desta forma:
\coords{Test}
Consegui carregar corretamente as coordenadas do local chamado dentro do comando (no caso "Teste"), mas quando tento gerar a URL, o LaTeX me dá muitos erros, a maioria deles ! Undefined control sequence
. Se eu remover \LAT
e \LNG
da linha onde a URL é gerada (dentro da definição do comando), não recebo nenhum erro, mas é claro que a URL não contém nenhuma coordenada, uma vez que elas estão armazenadas dentro das variáveis \LAT
e \LNG
.
Existe uma maneira de gerar corretamente o URL usando as variáveis definidas dentro do \href
comando?
Este é um exemplo de teste:
\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}
Respostas
Você pode usar o mesmo truque da minha resposta para recuperar substring 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}
Eu costumava \jobname
evitar destruir meus arquivos. Você pode usar qualquer nome de arquivo que desejar para o banco de dados.
Carregue o banco de dados uma vez, não sempre que ligar \coords
.
Eu sugiro a seguinte abordagem:
\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}
Eu sugiro essa abordagem porque com seu código existem alguns problemas:
Problema 1:
Seu \coords
-command produz tokens e \par
-tokens indesejados:
Eu o reescrevo com comentários indicando onde esses tokens indesejados surgem:
\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
}
Edição 2:
O hyperref-manual diz que os tokens no URL-argumento de \href
devem ser totalmente expansíveis.
Seus comandos \LAT
e \LNG
não são totalmente expansível porque a sua definição contém a palavra de controle token de \DTLfetch
enquanto o manual do-pacote Datatool diz claramente que
\DTLfetch{students}{regnum}{\RegNum}{forename}
é igual a
que indica que\dtlgetrowforvalue{students}{\dtlcolumnindex{students}{regnum}}{\RegNum}%
\dtlgetentryfromcurrentrow{\dtlcurrentvalue}{\dtlcolumnindex{students}{forename}}% \dtlcurrentvalue
\DTLfetch
(e, portanto, toda macro cuja expansão em algum estágio produz o token
\DTLfetch
) não é totalmente expansível conforme uma macro
\dtlcurrentvalue
é definida por
\dtlgetentryfromcurrentrow
.
Questão 3:
Duvido que seja necessário carregar o banco de dados a cada chamada para \coords
.
Questão 4:
Use o comando \DTLsetseparator
para definir o separador de entradas de um banco de dados como vírgula, embora este seja o padrão. Portanto, isso provavelmente está obsoleto.