Использование \ DTLfetch внутри \ href
Я пытаюсь создать новую команду в LaTeX, которая создает URL-адрес карты Google, указывающий на координаты, связанные с местом, указанным в качестве параметра в вызываемой команде (своего рода функция «поиска в таблице»). Места и относительные координаты хранятся внутри coords.CSV
файла и должны быть прочитаны с помощью datatool
пакета.
URL-адрес карты Google должен иметь такую структуру:
https://www.google.com/maps/?q=<LAT>,<LNG>
где <LAT>
и <LNG>
- координаты широты и долготы, загруженные из coords.CSV
файла, который структурирован следующим образом:
Place,LAT,LNG
Test,42.0000,42.0000
...
Вот как была определена команда:
\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}
}
Наконец, я использую новую команду таким образом:
\coords{Test}
Мне удалось правильно загрузить координаты места, вызываемого внутри команды (в данном случае «Test»), но когда я пытаюсь сгенерировать URL-адрес, LaTeX выдает много ошибок, большинство из которых таковы ! Undefined control sequence
. Если я удалю \LAT
и \LNG
от линии , где URL генерируется (внутри определения команды), я не получаю ошибку, но, конечно, URL не содержит каких - либо координат, так как они хранятся внутри \LAT
и \LNG
переменных.
Есть ли способ правильно сгенерировать URL-адрес с использованием определенных переменных внутри \href
команды?
Это тестовый пример:
\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}
Ответы
Вы можете использовать тот же трюк, что и в моем ответе, для получения подстроки `\ 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}
Раньше я \jobname
старался не затирать свои файлы. Вы можете использовать любое имя файла для базы данных.
Загружайте базу данных один раз, а не каждый раз при звонке \coords
.
Предлагаю следующий подход:
\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}
Я предлагаю этот подход, потому что с вашим кодом есть некоторые проблемы:
Выпуск 1:
Ваша \coords
-команда создает нежелательные пробелы и \par
-tokens:
Я переписываю его с комментариями, указывающими, откуда появляются эти нежелательные токены:
\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
}
Выпуск 2:
В руководстве по гиперссылкам говорится, что токены в аргументе URL-адреса \href
должны быть полностью расширяемыми.
Ваши команды \LAT
и \LNG
не могут быть полностью расширены, потому что их определение содержит токен контрольного слова, в \DTLfetch
то время как в руководстве к пакету данных четко сказано, что
\DTLfetch{students}{regnum}{\RegNum}{forename}
равно
что указывает на то, что\dtlgetrowforvalue{students}{\dtlcolumnindex{students}{regnum}}{\RegNum}%
\dtlgetentryfromcurrentrow{\dtlcurrentvalue}{\dtlcolumnindex{students}{forename}}% \dtlcurrentvalue
\DTLfetch
(и, следовательно, каждый макрос, расширение которого на каком-то этапе дает токен
\DTLfetch
) не может быть полностью расширен, поскольку макрос
\dtlcurrentvalue
определяется
\dtlgetentryfromcurrentrow
.
Выпуск 3:
Сомневаюсь, что нужно загружать базу данных при каждом обращении к \coords
.
Выпуск 4:
Вы используете команду \DTLsetseparator
для установки разделителя для записей базы данных на запятую, хотя это значение по умолчанию. Так что это, вероятно, устарело.