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...

lockstep
  • 250,273
Loic Rosnay
  • 8,167

4 Answers4

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}
David Carlisle
  • 757,742
  • thanks you for this interesting solution. What does \noalign do exactly ? – Loic Rosnay Jan 26 '12 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... – David Carlisle Jan 26 '12 at 13:13
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.

egreg
  • 1,121,712
  • 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) – Loic Rosnay Jan 26 '12 at 08:20
  • thanks. Could you explain what the \z@ does ? – Loic Rosnay Jan 26 '12 at 11:26
  • 1
    After \makeatletter, one can use \z@ to represent either the constant 0 or the length 0pt. – egreg Jan 26 '12 at 11:40
  • and why not simply putting 0 at this place ? because the \ifnum expects a command and not a number ? – Loic Rosnay Jan 26 '12 at 12:32
  • 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 Jan 26 '12 at 12:45
  • ok. Happy to learn a new good habit :) – Loic Rosnay Jan 26 '12 at 12:47
  • may i ask : How does act the \expandafter in your example ? – Loic Rosnay Jan 26 '12 at 12:49
  • It gets rid of \else or \fi; look in the site for it and you'll find many instances. – egreg Jan 26 '12 at 12:51
  • 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:-) – David Carlisle Jan 26 '12 at 13:26
  • @egreg: About the \expandafter : it only influences the speed of compilation, but removing them does not change the functionality of the command, am i right ? – Loic Rosnay Jan 27 '12 at 15:27
  • @nicolasroy No, they are essential. See this answer – egreg Jan 27 '12 at 15:36
  • Thank you for the solution. NEvertheless i encounter the following problem : I want to give \roystreqtest the caracter • as argument (it is the place holder in the TeX editor TexMaker), but the compilation says : ! TeX capacity exceeded, sorry [input stack size=5000].. Why ? – Loic Rosnay Jan 29 '12 at 18:59
  • @nicolasroy See edit – egreg Jan 29 '12 at 19:54
  • My next problem, is that the arguments in the command roystreqtest could be more complicated. They could contain some commands or some environnement. For example \begin{itemize}\item one\item two\end{itemize}. In this case, the compilation fails... – Loic Rosnay Feb 06 '12 at 13:52
  • @nicolasroy Please, make a follow-up question. – egreg Feb 06 '12 at 14:03
  • I'm sorry, but i don't know what a "follow-up question" is... – Loic Rosnay Feb 06 '12 at 15:04
  • @nicolasroy You're using the code I provided, but I can't know which one; modifying the question is not recommended, so you should write a new question, stating the problem with a MWE and put a link to this question. – egreg Feb 06 '12 at 15:09
  • ok. understood. – Loic Rosnay Feb 06 '12 at 15:19
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}

F. Pantigny
  • 40,250