\ href 내에서 \ DTLfetch 사용

Dec 04 2020

LaTeX에서 호출 된 명령 (일종의 "테이블 조회"기능)에서 매개 변수로 지정된 장소와 관련된 좌표를 가리키는 Google지도 URL을 만드는 새 명령을 만들려고합니다. 장소와 상대 좌표는 coords.CSV파일 내에 저장 되며 datatool패키지를 사용하여 읽어야 합니다.

Google지도 URL은 다음과 같이 구성되어야합니다.

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\LNGURL이 (명령 정의 내에서) 발생하는 줄에서, 나는 어떤 오류가 발생하지 않습니다,하지만 그들은 내부에 저장되어 있기 때문에 물론 URL이 어떤 좌표를 포함하지 않는 \LAT\LNG변수.

\href명령 내에 정의 된 변수를 사용하여 URL을 올바르게 생성하는 방법이 있습니까?

다음은 테스트 예입니다.

\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}

답변

4 egreg Dec 04 2020 at 11:05

'\ 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.

3 UlrichDiez Dec 04 2020 at 12:34

다음 접근 방식을 제안합니다.

\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 :

hyperref-manual은 URL 인수의 토큰 \href이 완전히 확장 가능해야 한다고 말합니다 .

귀하의 명령 \LAT\LNG그 정의는 토큰 제어 단어를 포함하고 있기 때문에이다 완전히 확장하지 \DTLfetchdatatool 패키지의 설명서를 분명히 있다고하면서

\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기본값이지만 데이터베이스 항목의 구분 기호를 쉼표로 설정 하기 위해 명령 을 사용합니다 . 따라서 이것은 아마도 구식입니다.