从 csv 文件定义新命令?

从 csv 文件定义新命令?

我想定义新命令并能够更改 csv 文件的输出。假设 csv 文件以分号分隔:

Name; Score
Max; 12
Peter; 32
Anna; 27

现在我想要在 LaTeX 中实现以下内容:

\newcommand{\Max}{12}
\newcommand{\Peter}{32}
\newcommand{\Anna}{27}

1. 基本解决方案:仅应从 csv 文件中读取数字(= 1232和)。命令名称(= 、和)可以硬编码。27\Max\Peter\Anna

2. 高级解决方案:循环遍历 csv 文件的所有行(可选:从第二行开始)并根据第一列中的名称(= 命令名称)和第二列中的分数(= 每个命令名称的期望输出)创建新命令。

我如何实现上述任何解决方案?有很多读取 csv 文件并在 LaTeX 中从中创建表格的示例,但我没有找到任何可以解决我的问题的方法。

提前致谢!


更新:添加了受以下网站启发的最小工作示例(MWE): https://www.uweziegenhagen.de/?p=3100

以下代码循环遍历我的 csv 文件并给出姓名和分数。这不能解决我的问题,但可能是其中的一部分:

\documentclass{article}

\usepackage{datatool}

\DTLsetseparator{;}
\DTLloaddb{scores}{test.csv}

\begin{document}
    \DTLforeach{scores}{%
        \name=Name,\score=Score}{%
        \name\score\\}
\end{document}

现在,当我尝试解决我的问题时,我无法以编程方式添加新命令名称(\Max\Peter\Anna)。我收到错误:Command \textbackslash already defined. \newcommand{\textbackslash \name}{\score}}。如果这可行,那将是“高级解决方案”,这将非常好:

\documentclass{article}

\usepackage{datatool}

\DTLsetseparator{;}
\DTLloaddb{scores}{test.csv}

\DTLforeach{scores}{%
    \name=Name,\score=Score}{%
    \newcommand{\textbackslash \name}{\score}}

\begin{document}
    \Max
    \Peter
    \Anna
\end{document}

答案1

\documentclass{article}
\usepackage{readarray}
\begin{filecontents*}[overwrite]{mydata.txt}
Name; Score
Max; 12
Peter; 32
Anna; 27
\end{filecontents*}

\begin{document}
\readarraysepchar{,}
\setsepchar{,/;}
\readdef{mydata.txt}\datadef
\ignoreemptyitems
\readlist*\datarray{\datadef}
\foreachitem\z\in\datarray[]{%
  \ifnum\zcnt=1\else
    \expandafter\xdef\csname\datarray[\zcnt,1]\endcsname
      {\datarray[\zcnt,2]}%
  \fi
}

The score for Max is \Max.

But Peter, with a score of \Peter, beats him.

The person from line 4 in the file, whose name I can't remember,
  is \datarray[4,1].  Her score is \datarray[4,2].
Oh, Anna?  Great!  I can just use \Anna.
\end{document}

在此处输入图片描述

答案2

这是不需要任何附加包的代码。仅使用 TeX 原语。

\documentclass{article}

\begin{document}

\def\readrow #1;#2;{\ifx^#2^\else 
   \expandafter\xdef\csname #1\endcsname{#2}%
   \expandafter\readrow\fi}
\def\startread #1;#2;{\readrow} % skip first row
\begingroup
   \endlinechar=`; \everyeof={;;} \catcode`\@=11
   \expandafter \startread \@@input mydata.txt %
\endgroup % 

The score for Max is \Max.

But Peter, with a score of \Peter, beats him.

I can just use \Anna.
\end{document}

答案3

您可以逐行读取文件(丢弃第一行),在分号处拆分行并执行定义:

\begin{filecontents*}{\jobname.dat}
Name; Score
Max; 12
Peter; 32
Anna; 27
\end{filecontents*}

\documentclass{article}

\ExplSyntaxOn

\NewDocumentCommand{\makecommands}{m}
 {
  \owmal_makecommands:n { #1 }
 }

\ior_new:N \g_owmal_makecommands_ior
\seq_new:N \l__owmal_makecommands_line_seq

\cs_new_protected:Nn \owmal_makecommands:n
 {
  \ior_open:Nn \g_owmal_makecommands_ior { #1 }
  \ior_get:NN \g_owmal_makecommands_ior \l_tmpa_tl % discard the first line
  \ior_map_inline:Nn \g_owmal_makecommands_ior
   {
    \seq_set_split:Nnn \l__owmal_makecommands_line_seq { ; } { ##1 }
    \cs_new:cpx
     { \seq_item:Nn \l__owmal_makecommands_line_seq { 1 } } % name of command
     { \seq_item:Nn \l__owmal_makecommands_line_seq { 2 } } % text
   }
 }

\ExplSyntaxOff

\makecommands{\jobname.dat}

\begin{document}

The score for Max is \Max

The score for Peter is \Peter

The score for Anna is \Anna

\end{document}

在此处输入图片描述

另一方面,您可以避免定义命令并将分数存储在按名称索引的属性列表中。

\begin{filecontents*}{\jobname.dat}
Name; Score
Max; 12
Peter; 32
Anna; 27
\end{filecontents*}

\documentclass{article}

\ExplSyntaxOn

\NewDocumentCommand{\readscores}{m}
 {
  \owmal_scores_read:n { #1 }
 }
\NewExpandableDocumentCommand{\getscore}{m}
 {
  \prop_item:Nn \g_owmal_scores_prop { #1 }
 }

\ior_new:N \g_owmal_scores_ior
\seq_new:N \l__owmal_scores_line_seq
\prop_new:N \g_owmal_scores_prop

\cs_new_protected:Nn \owmal_scores_read:n
 {
  \ior_open:Nn \g_owmal_scores_ior { #1 }
  \ior_get:NN \g_owmal_scores_ior \l_tmpa_tl % discard the first line
  \ior_map_inline:Nn \g_owmal_scores_ior
   {
    \seq_set_split:Nnn \l__owmal_scores_line_seq { ; } { ##1 }
    \prop_gput:Nxx \g_owmal_scores_prop
     { \seq_item:Nn \l__owmal_scores_line_seq { 1 } } % name
     { \seq_item:Nn \l__owmal_scores_line_seq { 2 } } % score
   }
 }

\ExplSyntaxOff

\readscores{\jobname.dat}

\begin{document}

The score for Max is \getscore{Max}

The score for Peter is \getscore{Peter}

The score for Anna is \getscore{Anna}

\end{document}

相关内容