使用“datatool”为新创建的命令分配值,最终用最后一个值填充所有内容

使用“datatool”为新创建的命令分配值,最终用最后一个值填充所有内容

我正在尝试通过 CSV 文件获取命令的值来创建新命令,并将datatool其加载到数据库中。问题是,使用此过程创建的每个命令都以分配给最后的数据库中的条目。

平均能量损失

这里我把使用的 CSV 和 MWE 都放了下来(感谢 Werner 提供的“命令包装器”,下落不明这里):

CSV 文件:

Campo,Valor,Aux
hallo,"Cmon",
another,"Piece",
whuzzat,"abc",

LaTeX用于加载CSV文件的文档:

\documentclass{article}

\usepackage{etoolbox}
\usepackage{datatool}

\newcommand{\assignto}[2]{%
    \ifcsdef{#2}{%
        \csdef{#1}{\csuse{#2}}%
    }{%
        \csdef{#1}{#2}%
    }%
}

\begin{document}
    \section*{Hard-coded variables}

    \newcommand{\abc}{ABC}
    \assignto{AAA}{aaa}\AAA\ %end to denote space
    \assignto{BBB}{abc}\BBB

    \section*{DB variables}

    \DTLloaddb{Datos}{datos.csv}
    \DTLforeach{Datos}{\campo=Campo,\valor=Valor,\valorb=Aux}{%
        \assignto{\campo}{\valor}
    }

    \hallo\ % It should be "Cmon"
    \another\ % It should be "Piece"
    \whuzzat\ % It should be "\abc", i.e. "ABC"
\end{document}

输出:

编译此 MWE 时的结果

答案1

你基本上是在做

\def\hallo{\valor}

\valor并且在进行定义之前你应该进行扩展:

\DTLforeach{Datos}{\campo=Campo,\valor=Valor,\valorb=Aux}{%
    \expandafter\assignto\expandafter{\expandafter\campo\expandafter}\expandafter{\valor}
}

当然还有更好更短的方法;例如

\newcommand\assignto[2]{\expandafter\assigntoaux\expandafter{#2}{#1}}
\newcommand{\assigntoaux}[2]{%
  \ifcsdef{#1}{%
    \csdef{#2}{\csuse{#1}}%
  }{%
    \csdef{#2}{#1}%
   }%
}

只是切换参数。

更好的方法是使用xparseexpl3

\begin{filecontents*}{\jobname.csv}
Campo,Valor,Aux
hallo,"Cmon",
another,"Piece",
whuzzat,"abc",
\end{filecontents*}

\documentclass{article}

\usepackage{datatool}
\usepackage{xparse}

\ExplSyntaxOn
\NewDocumentCommand{\assignto}{smm}
 {
  \IfBooleanTF{#1}
   {
    \logowriter_assignto:no { #2 } { #3 }
   }
   {
    \logowriter_assignto:nn { #2 } { #3 }
   }
 }
\cs_new_protected:Nn \logowriter_assignto:nn
 {
  \cs_new:cpn { #1 } { #2 }
 }
\cs_generate_variant:Nn \logowriter_assignto:nn { no }
\ExplSyntaxOff

\begin{document}
\section*{Hard-coded variables}

\newcommand{\abc}{ABC}
\assignto{AAA}{aaa}\AAA\ %end to denote space
\assignto{BBB}{abc}\BBB

\section*{DB variables}

\DTLloaddb{Datos}{\jobname.csv}
\DTLforeach{Datos}{\campo=Campo,\valor=Valor,\valorb=Aux}{%
  \assignto*{\campo}{\valor}
}

\hallo\ % It should be "Cmon"
\another\ % It should be "Piece"
\whuzzat\ % It should be "\abc", i.e. "ABC"

\end{document}

请注意,\assignto*在进行定义之前,第二个参数会扩展一次,这与\expandafter上面的长链标记相同,但要简单得多。

在此处输入图片描述

相关内容