如何测试 \ifnum 中的值,这些值是通过 \newcommand 和 \csvreader 从 csv 文件生成的?

如何测试 \ifnum 中的值,这些值是通过 \newcommand 和 \csvreader 从 csv 文件生成的?

我想根据是否存在非零数据点(对于此示例,\DepthOne并且\DepthThree需要进行测试)有条件地在报告中打印一些内容。

我首先使用 从 csv 表中读取值\csvreader,然后使用 为这些值分配标签\newcommand。然后使用 对标签进行测试\ifnum。下面实现中的行为不是我所希望的。例如,我missing number, treated as zero在句子前面得到了错误和奇怪的输出。此外,奇怪的是,我分配的标签之一(\SampleName)似乎没有持续存在。

我是否可以完成我所尝试的事情?正确的方法是什么?

\documentclass[10pt]{report}

\usepackage{csvsimple}
\usepackage{filecontents}

\newcommand*{\ThisRock}{examplecsv}

% Make up some data in a CSV file called examplecsv.csv
\begin{filecontents*}{\ThisRock.csv}
    SampleName,Depth1,DepthTwo,Depth3
    ROCK001,48,52,0
\end{filecontents*}

% Pick out specific data in the file and create labels for them to be read by latex
\newcommand*{\SampleName}{\csvreader{\ThisRock.csv}{1=\SampleName}{\SampleName}}
\newcommand*{\DepthOne}{\csvreader{\ThisRock.csv}{2=\Depth1}{\Depth1}}
\newcommand*{\DepthTwo}{\csvreader{\ThisRock.csv}{3=\DepthTwo}{\DepthTwo}}
\newcommand*{\DepthThree}{\csvreader{\ThisRock.csv}{4=\Depth3}{\Depth3}}

\begin{document}
% Show the data (normally this is underwater)
\csvautotabular{examplecsv.csv} \\

% Expect this to print the sentence twice fully (first time is okay, second time incomplete?)
The rock sampled was called \SampleName. \\
The rock sampled was called \SampleName. \\

% Because there is some non-zero data for the first sample, expect this to print the sentence
\ifnum\ifnum\DepthOne>0 1\else0\fi
=1 %
\noindent The first sample hole was drilled to \DepthOne~mm\\
\else
\\
\fi

% Because the data is zero for the third sample, expect this not to print the sentence
\ifnum\ifnum\DepthThree>0 1\else0\fi
=1 %
\noindent The third sample hole was drilled to \DepthThree~mm\\
\else
\\
\fi

\end{document}

答案1

这个答案实际上指的是你的评论egreg 的回答

当我希望访问上下文\samplename之外的标签时会发生什么\csvreader

您可以使用\csvreader上下文进行全局分配充分扩展局部“变量”/宏——为了获得值,“变量”需要扩展两次:

% Make up some data in a CSV file
\begin{filecontents*}{\jobname.csv}
SampleName,Depth1,DepthTwo,Depth3
ROCK001,48,52,0
ROCK002,1,2,3
\end{filecontents*}

\documentclass[10pt]{report}
\usepackage{csvsimple}

\newcount\Samplenumber
\newcommand*\GlobalSamplename{}%
\newcommand*\GlobalDepthone{}%
\newcommand*\GlobalDepthtwo{}%
\newcommand*\GlobalDepththree{}%
%
\newcommand*\GlobalSamplenamederrorefault{\texttt{??}}%
\newcommand*\GlobalDepthoneerrorefault{0}%
\newcommand*\GlobalDepthtwoerrorefault{0}%
\newcommand*\GlobalDepththreeerrorefault{0}%
%
\newcommand\PassFirstToSecond[2]{#2{#1}}%
\newcommand\expandtwice{}%
\long\def\expandtwice#1#{\innerexpandtwice{#1}}%
\newcommand\innerexpandtwice[2]{%
  \expandafter\expandafter\expandafter\PassFirstToSecond
  \expandafter\expandafter\expandafter{#2}{#1}%
}%

\makeatletter

\newcommand\ReadToMacrosSampleDataRowNumber[1]{%
  \@bsphack
  \begingroup
  \let\GlobalSamplename=\UndEfINeD
  \Samplenumber=0 %
  \csvreader{\jobname.csv}{%
    SampleName=\InsideCsvreaderSamplename,
    Depth1=\InsideCsvreaderDepthone,
    DepthTwo=\InsideCsvreaderDepthtwo,
    Depth3=\InsideCsvreaderDepththree,
  }{%
    \advance\Samplenumber by 1\relax
    %
    \ifnum#1=\Samplenumber\relax
      \expandtwice\gdef\GlobalSamplename{\InsideCsvreaderSamplename}%
      \expandtwice\gdef\GlobalDepthone{\InsideCsvreaderDepthone}%
      \expandtwice\gdef\GlobalDepthtwo{\InsideCsvreaderDepthtwo}%
      \expandtwice\gdef\GlobalDepththree{\InsideCsvreaderDepththree}%
    \fi
  }%
  \ifx\GlobalSamplename\UndEfINeD
    \@latex@error{Row #1 not available}{Seems your sheet of csv data does not have #1 rows.}%
    \global\let\GlobalSamplename=\GlobalSamplenamederrorefault
    \global\let\GlobalDepthone=\GlobalDepthoneerrorefault
    \global\let\GlobalDepthtwo=\GlobalDepthtwoerrorefault
    \global\let\GlobalDepththree=\GlobalDepththreeerrorefault
  \fi
  \endgroup
  \@esphack
}%
\makeatother

\begin{document}

\noindent\csvautotabular{\jobname.csv}

\bigskip

Reading data row number 2 via
\verb|\ReadToMacrosSampleDataRowNumber{2}| and
using placeholder-macros outside
\verb|\csvreader|:\ReadToMacrosSampleDataRowNumber{2}

The rock sampled was called \GlobalSamplename.

The rock sampled was called \GlobalSamplename.

\ifnum\GlobalDepthone>0 %
  The first sample hole was drilled to \GlobalDepthone~mm.
\fi

\ifnum\GlobalDepthtwo>0 %
  The second sample hole was drilled to \GlobalDepthtwo~mm.
\fi

\ifnum\GlobalDepththree>0 %
  The third sample hole was drilled to \GlobalDepththree~mm.
\fi

\noindent\hrulefill\null

Reading data row number 1 via
\verb|\ReadToMacrosSampleDataRowNumber{1}| and
using placeholder-macros outside
\verb|\csvreader|:\ReadToMacrosSampleDataRowNumber{1}

The rock sampled was called \GlobalSamplename.

The rock sampled was called \GlobalSamplename.

\ifnum\GlobalDepthone>0 %
  The first sample hole was drilled to \GlobalDepthone~mm.
\fi

\ifnum\GlobalDepthtwo>0 %
  The second sample hole was drilled to \GlobalDepthtwo~mm.
\fi

\ifnum\GlobalDepththree>0 %
  The third sample hole was drilled to \GlobalDepththree~mm.
\fi

\noindent\hrulefill\null

Reading non-existing data row number 3 via
\verb|\ReadToMacrosSampleDataRowNumber{3}| and
using placeholder-macros outside
\verb|\csvreader|---this yields an error-message and
errordefault-values:\ReadToMacrosSampleDataRowNumber{3}

The rock sampled was called \GlobalSamplename.

The rock sampled was called \GlobalSamplename.

\verb|\GlobalSamplename| is assigned the errordefault value \GlobalSamplename.

\verb|\GlobalDepthone| is assigned the errordefault value \GlobalDepthone.

\verb|\GlobalDepthtwo| is assigned the errordefault value \GlobalDepthtwo.

\verb|\GlobalDepththree| is assigned the errordefault value \GlobalDepththree.

\ifnum\GlobalDepthone>0 %
  The first sample hole was drilled to \GlobalDepthone~mm.
\fi

\ifnum\GlobalDepthtwo>0 %
  The second sample hole was drilled to \GlobalDepthtwo~mm.
\fi

\ifnum\GlobalDepththree>0 %
  The third sample hole was drilled to \GlobalDepththree~mm.
\fi

\end{document}

在此处输入图片描述

答案2

根据 @egreg 的建议,我做了更多研究,我发现我可以使用 datatool 来做我想做的事情:

\begin{filecontents*}{rockdata.csv}
SampleName,Depth1,DepthTwo,Depth3
ROCK001,48,52,0
\end{filecontents*}

\documentclass[10pt]{report}
\usepackage{datatool}

\DTLloaddb{rocks}{rockdata.csv}

\begin{document}

% This replaces the \newcommand step
\DTLforeach*{rocks}% database label
{\SampleName=SampleName,\DepthOne=Depth1,\DepthTwo=DepthTwo,\DepthThree=Depth3}% Assignment
{}% Things can be done in here

% But things can also seemingly be done out here too
\noindent The rock sampled was called \SampleName.\\
\dtlifnumeq{\DepthOne}{0}{\\}{The first sample hole was drilled to \DepthOne~mm\\}
\dtlifnumeq{\DepthTwo}{0}{\\}{The second sample hole was drilled to \DepthTwo~mm\\}
\dtlifnumeq{\DepthThree}{0}{\\}{The third sample hole was drilled to \DepthThree~mm\\}

\end{document}

更多大师方式

最终,我可以将丑陋的数据收集机制分离到样式文件中,并使用数据工具创建的标签来运行我想要的条件测试:

LaTex 文件:

\begin{filecontents*}{rockdata.csv}
SampleName,Depth1,DepthTwo,Depth3
ROCK001,48,52,0
\end{filecontents*}

\documentclass[10pt]{report}
\usepackage{datatool}

% User-defined package here
\usepackage{LoadRocks}

\begin{document}

% But things can also seemingly be done out here too
\noindent The rock sampled was called \SampleName.\\
\dtlifnumeq{\DepthOne}{0}{\\}{The first sample hole was drilled to \DepthOne~mm\\}
\dtlifnumeq{\DepthTwo}{0}{\\}{The second sample hole was drilled to \DepthTwo~mm\\}
\dtlifnumeq{\DepthThree}{0}{\\}{The third sample hole was drilled to \DepthThree~mm\\}

\end{document}

样式文件LoadRocks.sty

\ProvidesPackage{LoadRocks}[]
\DTLloaddb{rocks}{rockdata.csv}

\DTLforeach*{rocks}% database label
{\SampleName=SampleName,\DepthOne=Depth1,\DepthTwo=DepthTwo,\DepthThree=Depth3}% Assignment
{}

在此处输入图片描述

答案3

您误解了它\csvreader的作用。

% Make up some data in a CSV file
\begin{filecontents*}{\jobname.csv}
SampleName,Depth1,DepthTwo,Depth3
ROCK001,48,52,0
ROCK002,1,2,3
\end{filecontents*}

\documentclass[10pt]{report}
\usepackage{csvsimple}

\begin{document}

\csvautotabular{\jobname.csv}

\bigskip

\csvreader{\jobname.csv}{
    SampleName=\samplename,
    Depth1=\depthone,
    DepthTwo=\depthtwo,
    Depth3=\depththree,
  }
  {%
   The rock sampled was called \samplename.

   The rock sampled was called \samplename.

   \ifnum\depthone>0
     The first sample hole was drilled to \depthone~mm
   \fi

   \ifnum\depththree>0
     The third sample hole was drilled to \depththree~mm
   \fi

   \bigskip
  }

\end{document}

在此处输入图片描述

如果您希望在文档的任何位置提供所有数据,则必须对行进行索引。

% Make up some data in a CSV file
\begin{filecontents*}{\jobname.csv}
SampleName,Depth1,DepthTwo,Depth3
ROCK001,48,52,0
ROCK002,1,2,3
\end{filecontents*}

\documentclass{article}
\usepackage{csvsimple}
\usepackage{xparse}
\usepackage{siunitx}

\ExplSyntaxOn
\NewDocumentCommand{\rocks}{m}
 {
  \csvreader{#1}{}
   {
    \int_gincr:N \g_fejoia_rocks_int
    \prop_new:c { g_fejoia_rocks_ \int_to_arabic:n { \g_fejoia_rocks_int } _prop }
    \prop_gput:cno
     { g_fejoia_rocks_ \int_to_arabic:n { \g_fejoia_rocks_int } _prop }
     { SampleName } { \csvcoli }
    \prop_gput:cno
     { g_fejoia_rocks_ \int_to_arabic:n { \g_fejoia_rocks_int } _prop }
     { DepthOne } { \csvcolii }
    \prop_gput:cno
     { g_fejoia_rocks_ \int_to_arabic:n { \g_fejoia_rocks_int } _prop }
     { DepthTwo } { \csvcoliii }
    \prop_gput:cno
     { g_fejoia_rocks_ \int_to_arabic:n { \g_fejoia_rocks_int } _prop }
     { DepthThree } { \csvcoliv }
   }
}
\int_new:N \g_fejoia_rocks_int
\DeclareExpandableDocumentCommand{\getrock}{mm}
 {
  \prop_item:cn { g_fejoia_rocks_#1_prop } { #2 }
 }
\ExplSyntaxOff

\rocks{\jobname.csv}

\begin{document}

\csvautotabular{\jobname.csv}

\bigskip

\section{First rock}
The rock sampled was called \getrock{1}{SampleName}.

\ifnum\getrock{1}{DepthOne}>0
  The first sample hole was drilled to \SI{\getrock{1}{DepthOne}}{\mm}
\fi

\ifnum\getrock{1}{DepthThree}>0
  The third sample hole was drilled to \SI{\getrock{1}{DepthThree}}{\mm}
\fi

\section{Second rock}
The rock sampled was called \getrock{2}{SampleName}.

\ifnum\getrock{2}{DepthOne}>0
  The first sample hole was drilled to \SI{\getrock{2}{DepthOne}}{\mm}
\fi

\ifnum\getrock{2}{DepthThree}>0
  The third sample hole was drilled to \SI{\getrock{2}{DepthThree}}{\mm}
\fi

\end{document}

在此处输入图片描述

相关内容