使用 excel 中的变量定位 newcommand 并出现错误缺少 begin{document}

使用 excel 中的变量定位 newcommand 并出现错误缺少 begin{document}

我想使用 newcommand 来定位文本块 (xvalue, yvalue) 和文件 excel 中的变量 (\No)。

但是错误:缺少 begin{document} 并且当我使用 \xvalue\No 时我无法从 newcommand 获取值

我的最低限度的编码:

\RequirePackage{filecontents}
\begin{filecontents*}{test.csv}
Acol, Bcol, NoCol
A1,B1,1
A2,B2,2
A3,B3,3
A4,B5,4
A5,B5,5
\end{filecontents*}

\documentclass{article}
\usepackage{datatool}
\usepackage[absolute,overlay]{textpos}
\DTLloaddb{mydata}{test.csv}

\newcommand*{\xvalue1}{1}%
\newcommand*{\yvalue1}{2}%

\newcommand*{\xvalue2}{2}%
\newcommand*{\yvalue2}{3}%

\newcommand*{\xvalue3}{4}%
\newcommand*{\yvalue3}{1}%

\newcommand*{\xvalue4}{2.5}%
\newcommand*{\yvalue4}{3.5}%

\newcommand*{\xvalue5}{0.5}%
\newcommand*{\yvalue5}{7}%

\begin{document}

\DTLforeach*{mydata}{\A=Acol, \B=Bcol, \No=NoCol}%
{%
\begin{textblock*}{5cm}(\xvalue\No cm,\yvalue\No cm)
\A
\end{textblock*}
\pagebreak
\newpage
}%

\end{document}

预先感谢

答案1

我确实同意 Phelype 的观点,通常不应该在 中定义带有数字的宏(即使 可以这样做\csname...\endcsname),但我认为这里没有必要。相反,我认为您在这里寻找的是\ifcase。更详细地说,您定义命令的方式失败了,因为它们包含数字,并且正如 Phelype 指出的那样,这并不完全适用于\newcommand(*)。但是,您也不需要这样做。相反,您需要确保\xvalue1扩展为1\xvalue22\xvalue34等。这可以通过 实现\ifcase

\newcommand{\xvalue}[1]{\ifcase#1 % case #1=0
\or1% case #1=1
\or2% case #1=2
\or4% case #1=3
\or2.5% case #1=4
\or0.5% case #1=5
\fi}

使用相同的方法\yvalue并删除注释会产生一个有效的代码。

\RequirePackage{filecontents}
\begin{filecontents*}{test.csv}
Acol, Bcol, NoCol
A1,B1,1
A2,B2,2
A3,B3,3
A4,B5,4
A5,B5,5
\end{filecontents*}

\documentclass{article}
\usepackage{datatool}
\usepackage[absolute,overlay]{textpos}
\DTLloaddb{mydata}{test.csv}
\newcommand{\xvalue}[1]{\ifcase#1
\or1\or2\or4\or2.5\or0.5\fi}
\newcommand{\yvalue}[1]{\ifcase#1
\or2\or3\or1\or3.5\or7\fi}

\begin{document}

\DTLforeach*{mydata}{\A=Acol, \B=Bcol, \No=NoCol}%
{%
\begin{textblock*}{5cm}(\xvalue\No cm,\yvalue\No cm)
\A
\end{textblock*}
\pagebreak
\newpage
}%

\end{document}

在此处输入图片描述

答案2

[ 薛定谔的猫已经通过​​ 给出了(在我看来)最好的解决方案\ifcase
尽管如此,我的游戏本能现在已经被唤醒。 ;-) ]

Phelype Oleinik 已经指出,尝试使用数字/非字母来创建宏名称会导致问题。

如果您希望这样做,我可以提供一个宏\NameToCs,其作用如下:

\NameToCs⟨stuff not in curly braces and without curly braces⟩{NameOfCs}
⟨stuff not in curly braces and without curly braces⟩\NameOfCs

控制序列标记通过应用于 -argument来\NameOfCs创建。 - argument还可以包含数字等。可以为空。\csname..\endcsnameNameOfCs
NameOfCs
⟨stuff not in curly braces and without curly braces⟩

\RequirePackage{filecontents}
\begin{filecontents*}{test.csv}
Acol, Bcol, NoCol
A1,B1,1
A2,B2,2
A3,B3,3
A4,B5,4
A5,B5,5
\end{filecontents*}

\documentclass{article}

\begingroup
\makeatletter
\@firstofone{%
  \endgroup
  \newcommand\exchange[2]{#2#1}%
  \@ifdefinable\NameToCs{%
    \long\def\NameToCs#1#{\romannumeral0\InnerNameToCs{#1}}%
  }%
  \newcommand\InnerNameToCs[2]{%
    \expandafter\exchange\expandafter{\csname#2\endcsname}{ #1}%
  }%
}%


\usepackage{datatool}
\usepackage[absolute,overlay]{textpos}
\DTLloaddb{mydata}{test.csv}

\NameToCs\newcommand*{xvalue1}{1}%
\NameToCs\newcommand*{yvalue1}{2}%

\NameToCs\newcommand*{xvalue2}{2}%
\NameToCs\newcommand*{yvalue2}{3}%

\NameToCs\newcommand*{xvalue3}{4}%
\NameToCs\newcommand*{yvalue3}{1}%

\NameToCs\newcommand*{xvalue4}{2.5}%
\NameToCs\newcommand*{yvalue4}{3.5}%

\NameToCs\newcommand*{xvalue5}{0.5}%
\NameToCs\newcommand*{yvalue5}{7}%

\begin{document}

\DTLforeach*{mydata}{\A=Acol, \B=Bcol, \No=NoCol}%
{%
\begin{textblock*}{5cm}(\NameToCs{xvalue\No} cm,\NameToCs{yvalue\No} cm)%
\A
\end{textblock*}%
%\pagebreak %  Why \pagebreak and \newpage
%\newpage   %  _inside_ the \DTLforeach-loop?
            %  With \raggedbottom and 1 column-mode \pagebreak and \newpage are more or less the same.
            %  With \flushbottom and 1 column-mode \pagebreak yields that vertical gaps _between_
            %  paragraphs stretch so that the page is filled with text to the bottom while
            %  \newpage yields that the page is filled with a large empty vertical space from the last
            %  line of the page down to the bottom of the page.
            %  Therefore \newpage seems obsolete after \pagebreak.
            %  Besides this the textblock*-environment places things in a way where the page-building-apparatus
            %  does not "realize" that things are placed on the page. Therefore \pagebreak/\newpage in this
            %  example don't have an effect because the page-building-apparatus still "thinks" that no
            %  material for ejecting a page was collected yet that could be ejected due to \pagebreak/\newpage.
}%
\null
\newpage

\end{document}

在另一个数据库中拥有坐标(A(和 B)的 X 值和 Y 值)并通过嵌套循环合并两个数据库的处理可能也很有趣。
在下面的示例中,两个数据库共有的主键是“NoCol”。(我不清楚为什么将其命名为“NoCol”而不是“NumberOfRow”;-)

您可以通过另一个 .csv 文件执行此操作:

\RequirePackage{filecontents}
\begin{filecontents*}{test.csv}
Acol, Bcol, NoCol
A1,B1,1
A2,B2,2
A3,B3,3
A4,B5,4
A5,B5,5
\end{filecontents*}

\begin{filecontents*}{Acoordinates.csv}
NoCol, AXValue, AYValue
1,1,2
2,2,3
3,4,1
4,2.5,3.5
5,0.5,7
\end{filecontents*}

\documentclass{article}

\usepackage{datatool}
\usepackage[absolute,overlay]{textpos}
\DTLloaddb{mydata}{test.csv}
\DTLloaddb{myacoordinates}{Acoordinates.csv}

\begin{document}

\DTLforeach*{mydata}{\A=Acol, \B=Bcol, \NumberOfRowInTestCSV=NoCol}%
{%
  \DTLforeach*{myacoordinates}{\NumberOfRowInAcoordinatesCSV=NoCol, \Ax=AXValue, \Ay=AYValue}%
  {%
    \ifx\NumberOfRowInTestCSV\NumberOfRowInAcoordinatesCSV
      \begin{textblock*}{5cm}(\Ax cm,\Ay cm)%
      \A
      \end{textblock*}%
    \fi
  }%
}%
\null
\newpage

\end{document}

您还可以通过“手动”维护坐标数据库来完成此操作:

\RequirePackage{filecontents}
\begin{filecontents*}{test.csv}
Acol, Bcol, NoCol
A1,B1,1
A2,B2,2
A3,B3,3
A4,B5,4
A5,B5,5
\end{filecontents*}

\documentclass{article}

\usepackage{datatool}
\usepackage[absolute,overlay]{textpos}
\DTLloaddb{mydata}{test.csv}

\DTLnewdb{myacoordinates}%
\DTLaddcolumn{myacoordinates}{NoCol}%
\DTLaddcolumn{myacoordinates}{AXValue}%
\DTLaddcolumn{myacoordinates}{AYValue}%
\DTLnewrow{myacoordinates}%
  \DTLnewdbentry{myacoordinates}{NoCol}{1}%
  \DTLnewdbentry{myacoordinates}{AXValue}{1}%
  \DTLnewdbentry{myacoordinates}{AYValue}{2}%
\DTLnewrow{myacoordinates}%
  \DTLnewdbentry{myacoordinates}{NoCol}{2}%
  \DTLnewdbentry{myacoordinates}{AXValue}{2}%
  \DTLnewdbentry{myacoordinates}{AYValue}{3}%
\DTLnewrow{myacoordinates}%
  \DTLnewdbentry{myacoordinates}{NoCol}{3}%
  \DTLnewdbentry{myacoordinates}{AXValue}{4}%
  \DTLnewdbentry{myacoordinates}{AYValue}{1}%
\DTLnewrow{myacoordinates}%
  \DTLnewdbentry{myacoordinates}{NoCol}{4}%
  \DTLnewdbentry{myacoordinates}{AXValue}{2.5}%
  \DTLnewdbentry{myacoordinates}{AYValue}{3.5}%
\DTLnewrow{myacoordinates}%
  \DTLnewdbentry{myacoordinates}{NoCol}{5}%
  \DTLnewdbentry{myacoordinates}{AXValue}{0.5}%
  \DTLnewdbentry{myacoordinates}{AYValue}{7}%

\begin{document}

\DTLforeach*{mydata}{\A=Acol, \B=Bcol, \NumberOfRowInTestCSV=NoCol}%
{%
  \DTLforeach*{myacoordinates}{\NumberOfRowInAcoordinatesCSV=NoCol, \Ax=AXValue, \Ay=AYValue}%
  {%
    \ifx\NumberOfRowInTestCSV\NumberOfRowInAcoordinatesCSV
      \begin{textblock*}{5cm}(\Ax cm,\Ay cm)%
      \A
      \end{textblock*}%
    \fi
  }%
}%
\null
\newpage

\end{document}

也许 excel 可以为您创建一个 .csv 文件,其中还存储了 As(和 Bs)的坐标:

\RequirePackage{filecontents}
\begin{filecontents*}{test.csv}
Acol, Bcol, AXValue, AYValue
A1,B1,1,2
A2,B2,2,3
A3,B3,4,1
A4,B5,2.5,3.5
A5,B5,0.5,7
\end{filecontents*}

\documentclass{article}

\usepackage{datatool}
\usepackage[absolute,overlay]{textpos}
\DTLloaddb{mydata}{test.csv}
\DTLloaddb{myacoordinates}{Acoordinates.csv}

\begin{document}

\DTLforeach*{mydata}{\A=Acol, \B=Bcol, \Ax=AXValue, \Ay=AYValue}%
{%
  \begin{textblock*}{5cm}(\Ax cm,\Ay cm)%
  \A
  \end{textblock*}%
}%
\null
\newpage

\end{document}

相关内容