Menggunakan \ DTLfetch di dalam \ href
Saya mencoba membuat perintah baru di LaTeX yang membuat URL Google Map yang menunjuk ke koordinat yang terkait dengan tempat yang ditentukan sebagai parameter dalam perintah yang dipanggil (semacam fungsi "pencarian tabel"). Tempat dan koordinat relatif disimpan di dalam coords.CSV
file, dan harus dibaca menggunakan datatool
paket.
URL Google Map harus memiliki struktur seperti ini:
https://www.google.com/maps/?q=<LAT>,<LNG>
di mana <LAT>
dan <LNG>
apakah koordinat lintang dan bujur dimuat dari coords.CSV
file, yang disusun dengan cara ini:
Place,LAT,LNG
Test,42.0000,42.0000
...
Beginilah perintah didefinisikan:
\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}
}
Akhirnya, saya menggunakan perintah baru dengan cara ini:
\coords{Test}
Saya telah berhasil memuat koordinat tempat yang disebut di dalam perintah dengan benar (dalam hal ini "Test"), tetapi ketika saya mencoba membuat URL, LaTeX memberi saya banyak kesalahan, yang sebagian besar adalah ! Undefined control sequence
. Jika saya menghapus \LAT
dan \LNG
dari baris tempat URL dibuat (di dalam definisi perintah), saya tidak mendapatkan kesalahan apa pun, tetapi tentu saja URL tidak berisi koordinat apa pun, karena disimpan di dalam variabel \LAT
dan \LNG
.
Apakah ada cara untuk membuat URL dengan benar menggunakan variabel yang ditentukan di dalam \href
perintah?
Ini adalah contoh uji:
\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}
Jawaban
Anda dapat menggunakan trik yang sama seperti dalam jawaban saya untuk mengambil substring `\ 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}
Saya biasanya \jobname
menghindari pemukulan file saya. Anda dapat menggunakan nama file apa pun yang Anda inginkan untuk database.
Muat database sekali, tidak setiap kali Anda menelepon \coords
.
Saya menyarankan pendekatan berikut:
\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}
Saya menyarankan pendekatan ini karena dengan kode Anda ada beberapa masalah:
Masalah 1:
\coords
-Perintah Anda menghasilkan token-spasi dan \par
-tokens:
Saya menulis ulang dengan komentar yang menunjukkan di mana token yang tidak diinginkan ini muncul:
\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
}
Masalah 2:
Hyperref-manual mengatakan bahwa token dalam URL-argumen \href
harus dapat diperluas sepenuhnya.
Perintah Anda \LAT
dan \LNG
tidak sepenuhnya dapat diperluas karena definisinya berisi token kata kontrol \DTLfetch
sementara manual paket datatool dengan jelas mengatakan bahwa
\DTLfetch{students}{regnum}{\RegNum}{forename}
adalah sama dengan
yang menunjukkan bahwa\dtlgetrowforvalue{students}{\dtlcolumnindex{students}{regnum}}{\RegNum}%
\dtlgetentryfromcurrentrow{\dtlcurrentvalue}{\dtlcolumnindex{students}{forename}}% \dtlcurrentvalue
\DTLfetch
(dan karenanya setiap makro yang ekspansinya pada tahap tertentu menghasilkan token
\DTLfetch
) tidak dapat diperluas sepenuhnya saat makro
\dtlcurrentvalue
ditentukan oleh
\dtlgetentryfromcurrentrow
.
Masalah 3:
Saya ragu bahwa perlu memuat database dengan setiap panggilan ke \coords
.
Masalah 4:
Anda menggunakan perintah \DTLsetseparator
untuk mengatur pemisah untuk entri database menjadi koma meskipun ini adalah default. Jadi ini mungkin sudah usang.