![使用 excel 中的变量定位 newcommand 并出现错误缺少 begin{document}](https://linux22.com/image/405849/%E4%BD%BF%E7%94%A8%20excel%20%E4%B8%AD%E7%9A%84%E5%8F%98%E9%87%8F%E5%AE%9A%E4%BD%8D%20newcommand%20%E5%B9%B6%E5%87%BA%E7%8E%B0%E9%94%99%E8%AF%AF%E7%BC%BA%E5%B0%91%20begin%7Bdocument%7D.png)
我想使用 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
、\xvalue2
到2
、\xvalue3
到4
等。这可以通过 实现\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..\endcsname
NameOfCs
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}