我希望通过 CSV 生成的表格中的某些单元格为 \multicolumn - 它可以很好地用作表格的第 3 行,但如果第 2 行是 \multicolumn,则无法编译。下面比较使用 data1.csv(可以编译)和使用 data2.csv(会导致 \multispan ->\omit @multispan 错误)。我使用 \multicolumn 进行比此处显示的更复杂的格式化,但这个简单的问题阻止我继续。
\documentclass[border=5mm]{standalone}
\usepackage{csvsimple}
\begin{filecontents*}{data1.csv}
name
Value 1
Value 2
\multicolumn{1}{|@{}c@{}|}{Value 3}
\end{filecontents*}
\begin{filecontents*}{data2.csv}
name
Value 1
\multicolumn{1}{|@{}c@{}|}{Value 2}
Value 3
\end{filecontents*}
\begin{document}
\csvreader[%
head to column names,
table head= \hline,
tabular={ | c | },
late after line=\\\hline
]{data1.csv}{}{\name} % when data2.csv is used instead, this will not compile.
\end{document}
答案1
错误原因! Misplaced \omit.
与上一个问题正如@frank-mittelbach的回答指出的那样:
问题是
\multicolumn
只允许在单元格启动之前,即紧接在\\
或之后&
。在它们之间,所有允许的命令都是扩展的,并且作为扩展的一部分消失,没有副作用 [...]
对于OP的例子,
- 如果第一行数据(“值 1”)以 开头
\multicolumn
,则会引发错误,因为在table head
(\hline
)和第一行数据之间执行了多个赋值操作。 - 如果第二行数据(“值 2”)以 开头
\multicolumn
,由于 的特殊处理,仍会抛出错误late after first line
。它首先执行 的代码集late after first line
,然后重新定义内部宏 (\g__csvsim_hook_late_after_line_application_tl
) 来保存 的代码集。此赋值可防止在其后立即late after line
使用。\omit
- 如果第三行(“值 3”)或后面的数据行以 开头
\multicolumn
,那么由于after filter
和before line
在 OP 的示例中均为空,因此不会引发任何错误。
但这种成功是脆弱的:例如,一个无辜的人before line=\relax
会破坏它。
数据收集实用程序于csvsimple
v2.1.0 (2021-07-06)可以处理这种情况。注意:必须通过或csvsimple
加载高于 v1.22 的版本。\usepackage{csvsimple-l3}
\usepackage[l3]{csvsimple}
\begin{filecontents*}[force]{data1.csv}
name
Value 1
Value 2
\multicolumn{1}{|@{}c@{}|}{\bfseries Value 3}
\end{filecontents*}
\begin{filecontents*}[force]{data2.csv}
name
Value 1
\multicolumn{1}{|@{}c@{}|}{\bfseries Value 2}
Value 3
\end{filecontents*}
\documentclass{article}
\usepackage{csvsimple-l3}
\begin{document}
\parskip=.5ex
\noindent
Loading \verb|data1.csv|
\csvreader[
head to column names,
table head= \hline,
tabular={ | c | },
late after line=\\\hline,
]{data1.csv}{}{\name}
\noindent
[ERROR] Loading \verb|data1.csv| with \verb|before line=\relax|
% error "! Misplaced \omit."
\csvreader[
head to column names,
table head= \hline,
tabular={ | c | },
late after line=\\\hline,
before line=\relax
]{data1.csv}{}{\name}
\noindent
Loading \verb|data2.csv| with \verb|collect data|
\csvreader[
collect data,
head to column names,
late after line=\\\hline
]{data2.csv}{}{\csvexpval\name}
\begin{tabular}{|c|}
\hline
\csvdatacollection
\end{tabular}
\noindent
Loading \verb|data2.csv| with high-level options
\csvreader[
generic collected table=tabular,
generic table options={{|c|}},
table head= \hline,
head to column names,
late after line=\\\hline
]{data2.csv}{}{\csvexpval\name}
\end{document}