我正在使用 datatool 包将数据从 csv 获取到 LaTeX pdf 页面:
\documentclass{article}
\usepackage{datatool}
\begin{document}
\DTLloaddb{data}{students.csv}
\DTLforeach{data}
{\student=Name,\pointsa=Pointsa,\pointsb=Pointsb}
{\newpage
Student: \student\\
Points exercise A: \pointsa\\
Points exercise B: \pointsb
}
\end{document}
由于我的练习数量并不总是相同,因此我希望有一个模板可以仅根据 csv(基于该 csv 中的点数)自动适应练习数量。
在常规编程语言中,我会将“点”制成一个数组,并循环箭头来创建所有练习的点。
我如何实现此功能(练习数量可变但模板固定)?我可以看到两个解决方案,但不知道如何实现它们,或者是否有可能:
- 在 csv 中有一个包含点的数组(这可能吗?)
- 将所有点放在 csv 中的行尾,并获取点直到 EOL
我将非常感激任何关于如何解决这个问题的提示。如果有必要,我也可以使用另一个包。
答案1
我不知道您的数据是什么样的,甚至不确定我是否正确理解了您想要实现的目标,但也许您可以从这样简单的事情开始(但是,此解决方案不允许任意数量的列):
\documentclass{article}
\usepackage{datatool}
\begin{filecontents}[noheader]{students.csv}
Name, PointsA, PointsB, PointsC, PointsD
Student A, 10, 11, 12, 13
Student B, , 15, , 17
\end{filecontents}
\begin{document}
\DTLloaddb{data}{students.csv}
\DTLforeach{data}
{\student=Name,\pointsa=PointsA,\pointsb=PointsB,\pointsc=PointsC,\pointsd=PointsD}
{
\begin{tabular}{ll}
Student: & \student \\
\ifx\pointsa\empty\else Points exercise A: & \pointsa \\ \fi
\ifx\pointsb\empty\else Points exercise B: & \pointsb \\ \fi
\ifx\pointsc\empty\else Points exercise C: & \pointsc \\ \fi
\ifx\pointsd\empty\else Points exercise D: & \pointsd \\ \fi
\end{tabular}
\bigskip
}
\end{document}
在第二次阅读您的问题后,我假设您的数据存储在一个或多个 CSV 文件中,其中第一列是某种标识符(学生姓名),其余可以是包含整数值(或类似内容)的任意数量的列。
因此,我想出了利用该pgfplotstable
包的替代方法。此解决方案接受具有任意列数的 CSV 文件。第一列应包含学生姓名,接下来的列应包含各种考试的分数。此解决方案自动将考试名称设置为 A、B、C 等:
\documentclass{article}
\usepackage{pgfplotstable}
\pgfplotsset{compat=1.18}
\begin{filecontents}{studentsA.csv}
Name, PointsA, PointsB, PointsC, PointsD
Student A, 10, 11, 12, 13
Student B, , 15, , 17
\end{filecontents}
\begin{filecontents}{studentsB.csv}
Name, PointsA, PointsB, PointsC, PointsD, PointsE, PointsF
Student C, 10, 11, 12, 13, 14,
Student D, , 15, , 17, 18, 19
\end{filecontents}
\ExplSyntaxOn
\tl_new:N \l_studentstable_datarows_tl
\tl_new:N \l_studentstable_datacols_tl
\str_new:N \l_studentstable_currentstudent_str
\str_new:N \l_studentstable_tempexercise_str
\tl_new:N \l_studentstable_currentpointslist_tl
\NewDocumentCommand { \printStudentsTable } { m } {
\pgfplotstableread[col~sep=comma]{#1}{\studentsdata}
\pgfplotstablegetrowsof{\studentsdata}
\pgfmathsetmacro{\l_studentstable_datarows_tl}{\pgfplotsretval-1}
\pgfplotstablegetcolsof{\studentsdata}
\pgfmathsetmacro{\l_studentstable_datacols_tl}{\pgfplotsretval-1}
\foreach \i in {0,...,\l_studentstable_datarows_tl} {
\pgfplotstablegetelem{\i}{[index]0}\of{\studentsdata}
\str_set:Nx \l_studentstable_currentstudent_str { \pgfplotsretval }
\str_clear:N \l_studentstable_currentpointslist_tl
\foreach \j in {1,...,\l_studentstable_datacols_tl} {
\pgfplotstablegetelem{\i}{[index]\j}\of{\studentsdata}
\str_set:Nx \l_studentstable_tempexercise_str {
\str_uppercase:f { \int_to_alph:n { \j } }
}
\tl_gput_right:Nx \l_studentstable_currentpointslist_tl {
\str_if_empty:NTF \pgfplotsretval { } {
Points~exercise~\l_studentstable_tempexercise_str \c_colon_str &
\pgfplotsretval \\
}
}
}
\begin{tabular}{ l l }
Student: & \l_studentstable_currentstudent_str \\
\l_studentstable_currentpointslist_tl
\end{tabular}
\par
\bigskip
\par
}
}
\ExplSyntaxOff
\begin{document}
\printStudentsTable{studentsA.csv}
\printStudentsTable{studentsB.csv}
\end{document}
如果要打印考试描述,可以调整代码如下:
\documentclass{article}
\usepackage{pgfplotstable}
\pgfplotsset{compat=1.18}
\begin{filecontents}{studentsC.csv}
Name, Exam A, Exam B, Test C
Student C, 10, 11, 12
Student D, , 15,
\end{filecontents}
\ExplSyntaxOn
\tl_new:N \l_studentstable_datarows_tl
\tl_new:N \l_studentstable_datacols_tl
\str_new:N \l_studentstable_currentstudent_str
\str_new:N \l_studentstable_tempexercise_str
\tl_new:N \l_studentstable_currentpointslist_tl
\NewDocumentCommand { \printStudentsTable } { m } {
\pgfplotstableread[col~sep=comma]{#1}{\studentsdata}
\pgfplotstablegetrowsof{\studentsdata}
\pgfmathsetmacro{\l_studentstable_datarows_tl}{\pgfplotsretval-1}
\pgfplotstablegetcolsof{\studentsdata}
\pgfmathsetmacro{\l_studentstable_datacols_tl}{\pgfplotsretval-1}
\foreach \i in {0,...,\l_studentstable_datarows_tl} {
\pgfplotstablegetelem{\i}{[index]0}\of{\studentsdata}
\str_set:Nx \l_studentstable_currentstudent_str { \pgfplotsretval }
\str_clear:N \l_studentstable_currentpointslist_tl
\foreach \j in {1,...,\l_studentstable_datacols_tl} {
\pgfplotstablegetcolumnnamebyindex{\j}\of{\studentsdata}
\to\pgfplotsretval
\str_set:Nx \l_studentstable_tempexercise_str {
\pgfplotsretval
}
\pgfplotstablegetelem{\i}{[index]\j}\of{\studentsdata}
\tl_gput_right:Nx \l_studentstable_currentpointslist_tl {
\str_if_empty:NTF \pgfplotsretval { } {
Points~\l_studentstable_tempexercise_str \c_colon_str &
\pgfplotsretval \\
}
}
}
\begin{tabular}{ l l }
Student: & \l_studentstable_currentstudent_str \\
\l_studentstable_currentpointslist_tl
\end{tabular}
\par
\bigskip
\par
}
}
\ExplSyntaxOff
\begin{document}
\printStudentsTable{studentsC.csv}
\end{document}