问题陈述
我使用datatool
包的宏从 .csv 文件中\xDTLassignfirstmatch
确定给定作业的截止日期(由短代码标识,例如ex1
或),该文件包含一列(讲座日期列表)和一列(显示在相应日期截止的作业)。rd2
Date
Due
只要每堂课只交一份作业,这种方法就很好。然而,由于\xDTLassignfirstmatch
需要精确的,而不是部分匹配,如果在同一日期有多个作业到期,则匹配失败。
所以问题是:即使一个或多个其他作业也在同一天截止,我如何从 .csv 数据中确定特定作业的截止日期?
最小(非)工作示例
将以下代码复制到一个文件中main.tex
,并用 进行编译pdflatex main
。然后记下TODO
文件中的注释并进行相应的编辑。
主文本
\documentclass{article}
\usepackage{datatool}
\begin{filecontents}{schedule.csv}
Date,Due
2016-02-03,
2016-02-08,rd1
2016-02-10,"ex1, rd2"
\end{filecontents}
% NOTE: Uncomment only one of the following three lines at a time
\def\assignment{rd1}% Works, because no other assignment is due that day
%\def\assignment{ex1}% TODO: Breaks compilation, because rd2 is due the same day
%\def\assignment{rd2}% TODO: Breaks compilation, because ex1 is due the same day
\DTLloaddb{schedule}{schedule.csv}%
\xDTLassignfirstmatch{schedule}{Due}{\assignment}{\date=Date}%
\begin{document}
\noindent Date: \date
\end{document}
限制
我希望schedule.csv
尽可能保持结构一致。但是,如果有助于解决问题,应该可以用空格代替逗号(用于分隔当天截止的作业)。
对可能的解决方案的想法
\DTLifSubString
\DTLisinlist
包中的宏可能datatool
有助于解决这个问题,但我认为主要的挑战是用\xDTLassignfirstmatch
一些只需要部分匹配而不是完全匹配的宏来替换。我很确定这不存在,datatool
但必须从头开始编写(或从其他包中获取)?
Ulrike 原始解决方案的后续问题
Ulrike 提出了一种xparse
基于 的解决方案,该解决方案适用于给定的 MWE,但不适用于我的实际项目,因为一旦提取了作业截止日期,我实际上会使用它从 中提取更多数据schedule.csv
。
为了说明这一点,我添加了一个经过编辑的 MWE,它基于 Ulrike 的原始解决方案,但编译失败(参见TODO
文件中的注释)并出现错误Undefined control sequence
。我正在寻找一种方法来编译这个新的 MWE。
\documentclass{article}
\usepackage{datatool,xparse}
\begin{filecontents}{schedule.csv}
Date,Due,Foo
2016-02-03,,Bla
2016-02-08,rd1,Moo
2016-02-15,"ex1,rd3",Ha
2016-02-10,"ex1, rd2",Zoo
\end{filecontents}
\DTLloaddb{schedule}{schedule.csv}%
\ExplSyntaxOn
\DTLforeach{schedule}{\scheduledate=Date,\scheduledue=Due}
{
\clist_set:NV\l_tmpa_clist{\scheduledue}
%\clist_show:N\l_tmpa_clist
\clist_map_inline:Nn\l_tmpa_clist
{
\tl_if_exist:cF
{ g_firstschedule_#1_tl }
{
\tl_new:c {g_firstschedule_#1_tl}
\tl_gset:cV {g_firstschedule_#1_tl}{\scheduledate}
}
}
}
\NewDocumentCommand\firstassignment { m }
{
\tl_use:c { g_firstschedule_#1_tl }
}
\ExplSyntaxOff
\begin{document}
Date rd1: \firstassignment {rd1}
Date rd2: \firstassignment {rd2}
Date ex1: \firstassignment {ex1}
Date rd3: \firstassignment {rd3}
% TODO: The following line breaks compilation
\xDTLassignfirstmatch{schedule}{Date}{\firstassignment{rd1}}{\myfoo=Foo}%
\end{document}
答案1
您可以处理数据并检索日期。但请注意,如果您有大量条目,速度可能会变慢。
\documentclass{article}
\usepackage{datatool,xparse}
\begin{filecontents}{schedule.csv}
Date,Due
2016-02-03,
2016-02-08,"rd1"
2016-02-10,"ex1, rd2"
2016-02-15,"ex1,rd3"
\end{filecontents}
\DTLloaddb{schedule}{schedule.csv}%
\ExplSyntaxOn
\DTLforeach{schedule}{\scheduledate=Date,\scheduledue=Due}
{
\clist_set:NV\l_tmpa_clist{\scheduledue}
%\clist_show:N\l_tmpa_clist
\clist_map_inline:Nn\l_tmpa_clist
{
\tl_if_exist:cF
{ g_firstschedule_#1_tl }
{
\tl_new:c {g_firstschedule_#1_tl}
\tl_gset:cV {g_firstschedule_#1_tl}{\scheduledate}
}
}
}
\NewDocumentCommand\firstassignment { m }
{
\tl_use:c { g_firstschedule_#1_tl }
}
\ExplSyntaxOff
\begin{document}
Date rd1: \firstassignment {rd1}
Date rd2: \firstassignment {rd2}
Date ex1: \firstassignment {ex1}
Date rd3: \firstassignment {rd3}
\end{document}
编辑以便后续跟进。
\xDTLassignfirstmatch
只扩展一次,因此您不能使用复杂的命令,您需要先将值存储在一些简单的宏中。此外,\NewDocumentCommand 会创建不可扩展的健壮命令。因此,为了让您的后续工作正常进行,最好使用 \newcommand:
\documentclass{article}
\usepackage{datatool,xparse}
\DTLloaddb{schedule}{schedule.csv}%
\ExplSyntaxOn
\DTLforeach{schedule}{\scheduledate=Date,\scheduledue=Due}
{
\clist_set:NV\l_tmpa_clist{\scheduledue}
%\clist_show:N\l_tmpa_clist
\clist_map_inline:Nn\l_tmpa_clist
{
\tl_if_exist:cF
{ g_firstschedule_#1_tl }
{
\tl_new:c {g_firstschedule_#1_tl}
\tl_gset:cV {g_firstschedule_#1_tl}{\scheduledate}
}
}
}
\newcommand\firstassignment[1]
{
\tl_use:c { g_firstschedule_#1_tl }
}
\ExplSyntaxOff
\begin{document}
Date rd1: \firstassignment {rd1}
Date rd2: \firstassignment {rd2}
Date ex1: \firstassignment {ex1}
Date rd3: \firstassignment {rd3}
\edef\tmpdate{\firstassignment{rd1}}
\xDTLassignfirstmatch{schedule}{Date}{\tmpdate}{\myfoo=Foo}%
\myfoo
\end{document}