Menggunakan \ DTLfetch di dalam \ href

Dec 04 2020

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.CSVfile, dan harus dibaca menggunakan datatoolpaket.

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.CSVfile, 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 \LATdan \LNGdari 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 \LATdan \LNG.

Apakah ada cara untuk membuat URL dengan benar menggunakan variabel yang ditentukan di dalam \hrefperintah?

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

4 egreg Dec 04 2020 at 11:05

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 \jobnamemenghindari pemukulan file saya. Anda dapat menggunakan nama file apa pun yang Anda inginkan untuk database.

Muat database sekali, tidak setiap kali Anda menelepon \coords.

3 UlrichDiez Dec 04 2020 at 12:34

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 \hrefharus dapat diperluas sepenuhnya.

Perintah Anda \LATdan \LNGtidak sepenuhnya dapat diperluas karena definisinya berisi token kata kontrol \DTLfetchsementara manual paket datatool dengan jelas mengatakan bahwa

\DTLfetch{students}{regnum}{\RegNum}{forename}
adalah sama dengan

\dtlgetrowforvalue{students}{\dtlcolumnindex{students}{regnum}}{\RegNum}%

\dtlgetentryfromcurrentrow{\dtlcurrentvalue}{\dtlcolumnindex{students}{forename}}% \dtlcurrentvalue

yang menunjukkan bahwa \DTLfetch(dan karenanya setiap makro yang ekspansinya pada tahap tertentu menghasilkan token \DTLfetch) tidak dapat diperluas sepenuhnya saat makro \dtlcurrentvalueditentukan oleh \dtlgetentryfromcurrentrow.

Masalah 3:

Saya ragu bahwa perlu memuat database dengan setiap panggilan ke \coords.

Masalah 4:

Anda menggunakan perintah \DTLsetseparatoruntuk mengatur pemisah untuk entri database menjadi koma meskipun ini adalah default. Jadi ini mungkin sudah usang.