1

I want some cells in a table generated via CSV to be \multicolumn - it works fine as the 3rd row of the table, but if the 2nd row is \multicolumn, this will not compile. Compare using data1.csv (which does compile) with using data2.csv (which results in a \multispan ->\omit @multispan error) below. I am using \multicolumn for more complicated formatting than what I am showing here, but this simple problem is preventing me from proceeding.

\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 Answer 1

1

The cause of error ! Misplaced \omit. is the same as a previous question, as @frank-mittelbach's answer pointed out:

The problem is that \multicolumn is only allowed before a cell has started, i.e., directly after \\ or &. Between those all that is allowed are commands that expand and as part of the expansion vanish without side-effects [...]

For OP's example,

  • if the first data line ("Value 1") starts with \multicolumn, the error is thrown because there're several assignments executed between the table head (\hline) and first data line.
  • if the second data line ("Value 2") starts with \multicolumn, the error is still thrown because of the special treatment of late after first line. It first executes code set for late after first line, then redefines an internal macro (\g__csvsim_hook_late_after_line_application_tl) to hold the code set for late after line. This assignment prevents use of \omit right after it.
  • if the third ("Value 3") or latter data line starts with \multicolumn, then since both after filter and before line are empty in OP's example, no error is thrown.
    But this success is fragile: for example an innocent before line=\relax will break it.

The data collection utility introduced in csvsimple v2.1.0 (2021-07-06) can handle this situation. Note csvsimple newer than v1.22 must be loaded by either \usepackage{csvsimple-l3} or \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}

enter image description here

1
  • Thank you so much for your time explaining this!
    – James
    Oct 4, 2023 at 17:54

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .