次のようなタグと(ページ)番号を含む csv ファイルがあります。
tag,nr
t1,1
t2,5
t3,9
nr 列は、PDF ファイルのページ番号を参照します。各ページには対応するタグがあります。タグが指定されている場合は、LaTeX ドキュメントの図に対応するページを表示したいと思います。
datatools を使用すると、csv ファイルを読み込み、特定のタグのページ番号を取得できます。たとえば、タグの場合はt2
ページ番号を取得します5
。
しかし、そのページ番号をincludegraphicsの引数として渡すとpage=...
、エラーメッセージが表示されます。
「! 欠落した数字はゼロとして扱われます。」`
LaTeX 文字5
列を includegraphics が処理できるページ番号に変換するには、どのような追加手順を実行する必要がありますか?
問題を引き起こす簡略化されたバージョン (includegraphics の代わりにカウンターを使用) を次に示します。
\documentclass{article}
\usepackage{datatool}
\begin{document}
\DTLloaddb{tags}{prestags.csv}
\newcommand{\pagenr}{\DTLfetch{tags}{tag}{t2}{nr}}
\newcounter{snr}
\addtocounter{snr}{\pagenr}
\end{document}
% Output:
! Missing number, treated as zero.
<to be read again>
\let
l.10 \addtocounter{snr}{\pagenr}
これを修正するにはどうすればいいでしょうか?
答え1
問題は、\DTLfetch
マクロが拡張できないことです。ここで説明するテクニックを使用できます。
これを克服するには、次の例を実行してください。
\documentclass{article}
\begin{filecontents}{\jobname.csv}
tag,nr
t1,1
t2,5
t3,9
\end{filecontents}
\usepackage{datatool}
\newcommand{\getvar}[1]{\DTLfetchsave{\myvar}{tags}{tag}{#1}{nr}}
\newcommand{\DTLfetchsave}[5]{%
\edtlgetrowforvalue{#2}{\dtlcolumnindex{#2}{#3}}{#4}%
\dtlgetentryfromcurrentrow{\dtlcurrentvalue}{\dtlcolumnindex{#2}{#5}}%
\let#1\dtlcurrentvalue
}
\newcounter{snr}
\begin{document}
\DTLloaddb{tags}{prestags.csv}
\setcounter{snr}{3}
The counter value is \thesnr
\getvar{t2}
\addtocounter{snr}{\myvar}
The counter value is: \thesnr
\end{document}
答え2
ここでは、readarray
パッケージを使用して csv ファイルをダイジェストし、listofitems
読み取りを使用してデータをリストに配置します。マクロ\getvar
は拡張可能です。
\begin{filecontents*}[overwrite]{prestags.csv}
tag,nr
t1,1
t2,5
t3,9
\end{filecontents*}
\documentclass{article}
\usepackage{readarray,graphicx}
\begin{document}
\readarraysepchar{\\}
\readdef{prestags.csv}\mycsvdata
\setsepchar{\\/,}
\readlist*{\mycsvlist}{\mycsvdata}
\foreachitem\z\in\mycsvlist[]{%
\expandafter\gdef\csname mytag\mycsvlist[\zcnt,1]\expandafter
\endcsname\expandafter{\expandafter
\mycsvlist\expandafter[\zcnt,2]}%
}
\newcommand\getvar[1]{\csname mytag#1\endcsname}
The t2 tag corresonds with page \getvar{t2}
\includegraphics[page=\getvar{t3},scale=.6]{readarray.pdf}
\end{document}
答え3
スクラッチマクロをグローバルに定義しても構わない場合は、おそらく以下を使用できます\DTLassignfirstmatch
。
次の例をコンパイルすると、2 つのエラー メッセージが表示されます。
これは、存在しない値を取得しようとした場合に何が起こるかを確認できるように意図的に行われます。
\begin{filecontents*}{prestags.csv}
tag,nr
t1,1
t2,5
t3,9
\end{filecontents*}
\makeatletter
\newcommand\MyStuffDTLfetchsavePackageError[7]{%
\PackageError{#1}{#7}{%
In order to retrieve from database `#2`\MessageBreak
the value of the key `#5` in the first row\MessageBreak
where the key `#3` has value `#4`,\MessageBreak
database `#2` must exist and have keys\MessageBreak
`#3` and `#5` and a row where the key `#3`\MessageBreak
has the value `#4`.%
}%
\global\let#6=\dtlnovalue
}%
\DeclareRobustCommand{\MyStuffDTLfetchsave}[5]{%
%#1 = macro to store as result
%#2 = data base name
%#3 = key 1
%#4 = value of key 1
%#5 = key 2
\@bsphack
\DTLifdbexists{#2}{%
\DTLifhaskey{#2}{#3}{%
\DTLifhaskey{#2}{#5}{%
\global\let#1=\dtlnovalue
\DTLassignfirstmatch{#2}{#3}{#4}{#1=#5}%
\ifx#1\dtlnovalue\expandafter\@firstofone\else\expandafter\@gobble\fi
{%
\MyStuffDTLfetchsavePackageError{My Stuff}{#2}{#3}{#4}{#5}{#1}%
{In data base `#2' no row's key `#3' holds the value `#4'}%
}%
}{%
\MyStuffDTLfetchsavePackageError{My Stuff}{#2}{#3}{#4}{#5}{#1}%
{There is no key `#5' in data base `#2'}%
}%
}{%
\MyStuffDTLfetchsavePackageError{My Stuff}{#2}{#3}{#4}{#5}{#1}%
{There is no key `#3' in data base `#2'}%
}%
}{%
\MyStuffDTLfetchsavePackageError{My Stuff}{#2}{#3}{#4}{#5}{#1}%
{Data base `#2' doesn't exist}%
}%
\@esphack
}%
\makeatother
\documentclass{article}
\usepackage{datatool}
\newcounter{snr}
\begin{document}
\DTLloaddb{tags}{prestags.csv}
\setcounter{snr}{3}%
\noindent The counter value is: \thesnr
\MyStuffDTLfetchsave{\scratchy}{tags}{tag}{t1}{nr}%
\ifx\scratchy\dtlnovalue
\noindent The value of the key `nr` in the row where the key `tag` has the value `t1` could not be retrieved.
\noindent Calculations where this value would have been used were not performed.
\else
\noindent The value of the key `nr` in the row where the key `tag` has the value `t1` is: \scratchy
\addtocounter{snr}{\scratchy}%
\noindent After adding that value to the counter, the counter value is: \thesnr
\fi
\MyStuffDTLfetchsave{\scratchy}{tags}{tag}{t2}{nr}%
\ifx\scratchy\dtlnovalue
\noindent The value of the key `nr` in the row where the key `tag` has the value `t2` could not be retrieved.
\noindent Calculations where this value would have been used were not performed.
\else
\noindent The value of the key `nr` in the row where the key `tag` has the value `t2` is: \scratchy
\addtocounter{snr}{\scratchy}%
\noindent After adding that value to the counter, the counter value is: \thesnr
\fi
\MyStuffDTLfetchsave{\scratchy}{tags}{tag}{t3}{nr}%
\ifx\scratchy\dtlnovalue
\noindent The value of the key `nr` in the row where the key `tag` has the value `t3` could not be retrieved.
\noindent Calculations where this value would have been used were not performed.
\else
\noindent The value of the key `nr` in the row where the key `tag` has the value `t3` is: \scratchy
\addtocounter{snr}{\scratchy}%
\noindent After adding that value to the counter, the counter value is: \thesnr
\fi
\MyStuffDTLfetchsave{\scratchy}{tags}{tag}{t4}{nr}%
\ifx\scratchy\dtlnovalue
\noindent The value of the key `nr` in the row where the key `tag` has the value `t4` could not be retrieved.
\noindent Calculations where this value would have been used were not performed.
\else
\noindent The value of the key `nr` in the row where the key `tag` has the value `t4` is: \scratchy
\addtocounter{snr}{\scratchy}%
\noindent After adding that value to the counter, the counter value is: \thesnr
\fi
\end{document}
答え4
提案されたようにフォローDTLfetch
質問内の行は次の 2 行に置き換えることができます。
\DTLgetlocation{\rownr}{\colnr}{tags}{t2}
\DTLgetvalue{\pagenr}{tags}{\rownr}{\dtlcolumnindex{tags}{nr}}
これは単純な変更だったので、最終的にはこれを使用しました。