7

I encounter various problems when i want to control the display of a table with a ifthenelse test. For example, consider the following M(non)WE :

\documentclass{article}
\usepackage{multirow}
\usepackage{ifthen}
\newcommand{\essai}[1]{
\begin{tabular}{cc}
    a&b \\ \hline
    \ifthenelse{\equal{#1}{coucou}}{\multicolumn{2}{|c|}{oui - #1} \\ \hline}{non&#1 \\ \hline} 
\end{tabular}
}
\begin{document}
  \essai{coucou}
\end{document}

If i call \essai{hallo}, then the ifthenelse test is false, and it compiles : the second line of the table has 2 columns, as expected. If i call \essai{coucou}, then the test is true and i would expect to have a multicolumn line. But it gives a compilation error Misplaced \omit...

4 Answers 4

5

\multicolumn must be the first thing TeX sees in a table cell, after expanding commands; unfortunately, the workings of \ifthenelse leave something before \multicolumn when the test is computed false.

Use a different test making command: in this case, \ifboolexpe from etoolbox (notice the final "e"), might seem promising.

Unfortunately, also the way etoolbox implements the string equality test leads to unexpandable commands before TeX can see \multicolumn, so a direct approach must be used:

\documentclass{article}
\makeatletter
\newcommand{\roystreqtest}[2]{%
  \ifnum\pdfstrcmp{#1}{#2}=\z@
    \expandafter\@firstoftwo
  \else
    \expandafter\@secondoftwo
  \fi}
\makeatother
\newcommand{\essai}[1]{%
  \begin{tabular}{cc}
  a&b \\ \hline
  \roystreqtest{#1}{coucou}%
    {\multicolumn{2}{|c|}{oui - #1} \\ \hline}
    {non&#1 \\ \hline} 
  \end{tabular}%
}

\begin{document}
\essai{coucou}

\essai{noncoucou}
\end{document}

If you have to compare strings that are not made only of ASCII printable characters, it's safer to say

\newcommand{\roystreqtest}[2]{%
  \ifnum\pdfstrcmp{\detokenize{#1}}{\detokenize{#2}}=\z@
    \expandafter\@firstoftwo
  \else
    \expandafter\@secondoftwo
  \fi}

If you're bold, you can use an already defined infrastructure: LaTeX3 provides an expandable equality test for strings: the definition of \roystreqtest can be

\usepackage{expl3}
\ExplSyntaxOn
\cs_set_eq:NN \roystreqtest \str_if_eq:nnTF
\ExplSyntaxOff

and the rest would be the same.

18
  • I always wanted to learn how to use etoolbox, by i was scarred by the number of different commands, and the lack of examples in the documentation. It would help me if you could give me the synthaxe for my example (the test #1 = coucou) Commented Jan 26, 2012 at 8:20
  • thanks. Could you explain what the \z@ does ? Commented Jan 26, 2012 at 11:26
  • 1
    After \makeatletter, one can use \z@ to represent either the constant 0 or the length 0pt.
    – egreg
    Commented Jan 26, 2012 at 11:40
  • 1
    It's a habit; writing 0 is good, provided a space (or end-of-line) follows it: \ifnum...=0\@firstoftwo...\fi might give unexpected results. Conversely, \z@\@firstoftwo would be safe.
    – egreg
    Commented Jan 26, 2012 at 12:45
  • 3
    \z@ is quicker than 0 as it's a token that is already a number and so doesn't scan ahead. "0 " scans ahead and consumes the space "0foo" scans ahead and re-inserts the f into the input. Probably these days it's not noticeable but in 1980's it could save you enough time to go for a coffee:-) Commented Jan 26, 2012 at 13:26
9

If you are an old timer and not using e* tools then you need to hide the conditionals from TeX's alignment scanner. This is tricky in general but if you know your test is always the first thing in a row (ie always in the first cell in a row) then you can do the tests in a \noalign and come out with a suitably defined temporary macro.

This seems to work for your example

\documentclass{article}
\usepackage{multirow}
\usepackage{ifthen}
\newcommand{\essai}[1]{
\begin{tabular}{cc}
    a&b \\ \hline
\noalign{%
    \ifthenelse{\equal{#1}{coucou}}%
        {\gdef\hmm{\multicolumn{2}{|c|}{oui - #1} \\ \hline}}%
        {\gdef\hmm{non&#1 \\ \hline}}%
}\hmm 
\end{tabular}
}
\begin{document}

  \essai{coucou}

  \essai{xoucou}


\end{document}
2
  • thanks you for this interesting solution. What does \noalign do exactly ? Commented Jan 26, 2012 at 12:40
  • 2
    \noalign is a TeX primitive designed so that you can put in some vertical matter for example a paragraph that does not take part in the table, and then the table rows continue afterwards. The amsmath alignments have a command that uses noalign in this way but if you search for noalign in the latex sources (eg latex.ltx) you'll see it is used all over the place for the reason given here. It is used in processing ` \\ ` so it can handle looking for optional arguments, it's used in \hline to hide the code that looks for a following \hline again so that \multicolumn works. etc... Commented Jan 26, 2012 at 13:13
1

You can do your tests outside the \table:

\ifthenelse{\boolean{expr}}
    {\gdef\temp{\multicolumn{...}}}
    {\gdef\temp{something else}}
...
\begin{tabular}{..}
...\\
\temp
...
1

The environment {NiceTabular} of nicematrix provides a command \Block which gives features similar to \multicolumn and \multirow.

There is no problem using \Block inside \ifthenelse.

\documentclass{article}
\usepackage{ifthen}
\usepackage{nicematrix}

\newcommand{\essai}[1]{
\begin{NiceTabular}{cc}
    text & text \\ \hline
    \ifthenelse{\equal{#1}{coucou}}{\Block{1-2}{oui - #1} \\ \hline} {non&#1 \\ \hline} 
\end{NiceTabular}
}
\begin{document}
  \essai{coucou}
\end{document}

You must log in to answer this question.

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