Tengo un archivo csv con etiquetas y números (de página), como sigue:
tag,nr
t1,1
t2,5
t3,9
La columna nr se refiere a los números de página en un archivo pdf. Cada página tiene una etiqueta correspondiente. Dada una etiqueta, quiero mostrar la página correspondiente en una figura en mi documento de látex.
Con datatools puedo cargar el archivo csv y recuperar el número de página de una etiqueta determinada. Por ejemplo, para la etiqueta t2
obtengo la página número 5
.
Pero ahora, cuando introduzco ese número de página como page=...
argumento para incluir gráficos, aparece el mensaje de error.
"! Número faltante, tratado como cero."`
¿Qué paso adicional debo tomar para convertir la 5
cadena de látex en un número de página que incluya gráficos pueda manejar?
Aquí hay una versión simplificada (que usa contadores en lugar de incluir gráficos) que desencadena el problema:
\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}
¿Qué debo hacer para solucionar esto?
Respuesta1
El problema es que la \DTLfetch
macro no es ampliable. Puedes utilizar la técnica que se describe aquí:
para superar esto. Aquí hay un ejemplo resuelto:
\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}
Respuesta2
Aquí, uso el readarray
paquete para digerir el archivo csv y una listofitems
lectura para colocar los datos en una lista. La macro \getvar
es ampliable.
\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}
Respuesta3
Si no le importa definir una macro temporal globalmente, probablemente pueda usar \DTLassignfirstmatch
:
Al compilar el siguiente ejemplo, aparecen dos mensajes de error.
Esto es a propósito para que pueda ver qué sucede en caso de intentar recuperar valores no existentes.
\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}
Respuesta4
Como lo sugiere@cabohah, la DTLfetch
línea de la pregunta se puede reemplazar por las dos líneas siguientes:
\DTLgetlocation{\rownr}{\colnr}{tags}{t2}
\DTLgetvalue{\pagenr}{tags}{\rownr}{\dtlcolumnindex{tags}{nr}}
Como se trataba de un cambio simple, esto es lo que terminé usando.