5

I have the following code with a command that creates rows for a tabular:

\documentclass[letterpaper,10pt]{article}
\usepackage[utf8]{inputenc}
\usepackage{xstring}

\newcommand*{\condrow}[2]{
\IfEqCase{#1}{
 {l}{#2 & & \\}
 {r}{ & & #2 \\}
 {c}{ & #2 & \\}
 {m}{\multicolumn{3}{c}{#2} \\}
}[\PackageError{condrow}{Undefined option: #1}{}]
}

\begin{document}
\begin{tabular}{|c|c|c|}
 \condrow{l}{left}
 \condrow{r}{right}
 \condrow{c}{center}
 \multicolumn{3}{c}{manual multi} \\ % WORKS
 \condrow{m}{condrow multi} % FAILS
\end{tabular}
\end{document}

While using the \multicolumn directly in the tabular works, using \multicolumn through the command \condrow fails. My guess is that \IfEqCase in \condrow prepends something to the beginning of the \multicolumn command, triggering the following error:

! Misplaced \omit.
\multispan ->\omit 
                   \@multispan 
l.20  \condrow{m}{condrow multi}
                                 % FAILS

Prepending \\ before \multicolumn in the command makes the error disappear, but inserts an empty row. The problem Misplaced \omit. \multispan with \newcommand is similar. However, the answers do not solve my case. I have tried using the ifthen package for branching without success.

Any ideas how to fix this?

4 Answers 4

3

An expl3 solution:

\documentclass[letterpaper,10pt]{article}
\usepackage{xparse}

\ExplSyntaxOn
\DeclareExpandableDocumentCommand{\condrow}{ m m }
 {
  \str_case:nnF { #1 }
   {
    { l } { #2 &    &    \\ }
    { r } {    &    & #2 \\ }
    { c } {    & #2 &    \\ }
    { m } { \multicolumn{3}{c}{#2} \\ }
   }
   { \PackageError{condrow}{Undefined~option:~#1}{<explanation>} }
 }
\ExplSyntaxOff

\begin{document}
\begin{tabular}{|c|c|c|}
  \condrow{l}{left}
  \condrow{r}{right}
  \condrow{c}{center}
  \condrow{m}{condrow multi}
\end{tabular}
\end{document}

This has the advantage of being more easily extended to accept new options.

enter image description here

4
  • The code gives me ! Undefined control sequence. \condrow #1#2-&gt;\str_case:nnF {#1}{{l}{#2&&\\}{r}{&&#2\\}{c}{&#2&\\}{m}{\mult... l.20 \condrow{l}{left}
    – faf0
    Commented Aug 29, 2013 at 17:05
  • 1
    @faf0 Upgrade your TeX installation. Which one are you using?
    – egreg
    Commented Aug 29, 2013 at 17:06
  • I am using texlive-full on Ubuntu 12.04.
    – faf0
    Commented Aug 29, 2013 at 17:10
  • @faf0 Sorry, but the Ubuntu/Debian TeX distribution is really outdated.
    – egreg
    Commented Aug 29, 2013 at 17:25
6

As Werner said you need an expandable test. As you are just comparing single letters an alternative to \pdfstrcmp is \if

\documentclass[letterpaper,10pt]{article}

\newcommand*{\condrow}[2]{%
       \if l#1 #2 & & \\%
  \else\if r#1 &  & #2 \\%
  \else\if c#1 & #2 & \\%
  \else\if m#1\multicolumn{3}{c}{#2} \\%
  \else\PackageError{condrow}{Undefined option: #1}{}%
  \fi\fi\fi\fi%
}


\begin{document}
\begin{tabular}{|c|c|c|}
  \condrow{l}{left}
  \condrow{r}{right}
  \condrow{c}{center}
  \multicolumn{3}{c}{manual multi} \\ % WORKS
  \condrow{m}{condrow multi} % WORKS
\end{tabular}
\end{document}
4

This is exactly the same error as in Misplaced \omit. \multispan with \newcommand - it's just not that visible. The problem is that xstring's \IfEqCase is not expandable since it makes assignments to perform the comparison. Instead, using a trick from On testing two fully expanded character strings for equality, you can utilize pdfTeX's \pdfstrcmp to compare strings in an expandable way:

enter image description here

\documentclass[letterpaper,10pt]{article}
\makeatletter
\newcommand*{\condrow}[2]{%
  \ifnum\pdfstrcmp{#1}{l}=\z@ #2 & & \\
  \else\ifnum\pdfstrcmp{#1}{r}=\z@ & & #2 \\
  \else\ifnum\pdfstrcmp{#1}{c}=\z@ & #2 & \\
  \else\ifnum\pdfstrcmp{#1}{m}=\z@ \multicolumn{3}{c}{#2} \\
  \else\PackageError{condrow}{Undefined option: #1}{}%
  \fi\fi\fi\fi%
}
\makeatother

\begin{document}
\begin{tabular}{|c|c|c|}
  \condrow{l}{left}
  \condrow{r}{right}
  \condrow{c}{center}
  \multicolumn{3}{c}{manual multi} \\ % WORKS
  \condrow{m}{condrow multi} % WORKS
\end{tabular}
\end{document}
0

For information, if you use {NiceTabular} of nicematrix, with its built-in command \Block instead of \multicolumn, you have directly the output you wish (because \Block is a protected command which works as is).

However, you need several compilations because nicematrix uses PGF/Tikz nodes under the hood.

\documentclass[letterpaper,10pt]{article}
\usepackage{nicematrix}
\usepackage{xstring}

\newcommand*{\condrow}[2]{
\IfEqCase{#1}{
 {l}{#2 & & \\}
 {r}{ & & #2 \\}
 {c}{ & #2 & \\}
 {m}{\Block{1-3}{#2} & & \\}
}[\PackageError{condrow}{Undefined option: #1}{}]
}

\begin{document}
\begin{NiceTabular}{|c|c|c|}
 \condrow{l}{left}
 \condrow{r}{right}
 \condrow{c}{center}
 \multicolumn{3}{c}{manual multi} \\ 
 \condrow{m}{condrow multi}
\end{NiceTabular}
\end{document}

Output of the above code

You must log in to answer this question.

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