2

TLDR: I try to write a class that shows/hides table rows conditionally. When a row is hidden just before \multicolumn is used, an error is triggered.

Let me first give you an M(N)WE for simpler dicussion:

\documentclass{article}
\RequirePackage{xifthen}
% Put some data in macros. This wil be imported later using \input{...}
\newcommand{\TaskA}{Some description comes here}
\newcommand{\TaskB}{Some other description}
\newcommand{\TaskC}{}
\newcommand{\HoursA}{1}
\newcommand{\HoursB}{3}
\newcommand{\HoursC}{0}

\newcommand{\printline}[1]{\ifthenelse{ \equal{\csname Task#1\endcsname}{} }{}{%
    #1 & \csname Task#1\endcsname & \csname Hours#1\endcsname & 42 \\%
}}

\begin{document}
\section{Correct behavior}
\begin{tabular}{|l l | c c }
A & Some description comes here & 1 & 42 \\
B & Some other description & 3 & 42 \\
\multicolumn{2}{|r|}{Sum:} & 4 & 82 \\
\end{tabular}

\section{Error is created}
\begin{tabular}{| l l | c c }
\printline{A}
\printline{B}
\printline{C}
\multicolumn{2}{|r|}{Sum:} & 4 & 82 \\
\end{tabular}
\end{document}

I wanted to write a class that outputs a table depending on the values of a set of macros. I dropped here the iteration thing and wrote it explicitly for sake of simplicity. If a condition is met (in the MWE only an empty task name is checked but the check is more complex in the final class) the complete row should be hidden.

I added one table that is rendered completely manually and that is working perfectly fine. However once I use macro to typeset a single row, that does no longer work as expected. First, I get a LaTeX error

Misplaced \omit.
\multispan ->\omit 
                   \@multispan 
l.28 \multicolumn{2}{|r|}{Sum:}
                                & 4 & 82 \\

Additionally, the output has no real cell spanning over two columns but the first column is somehow added as well.

LaTeX output of test code

Fun fact if one disables the row B and enables C (just switch the macro names), the effect seems not to happen. So I suspect that I am triggering an issue with the \multicolumn macro.

After reading this post and trying out the approach with DeclareExpandableDocumentCommand, I suspect the problem is the \ifthenelse structure. Am I required to go with basic (plain) TeX here?


Edit 1:
I got some anseers/comments (thank you!) but I have the problem that I cannot simply expand these to my needs (with my state of knowledge). So I might need to specify what tests I need more explictly: First, you must knw that there are not one but 2 time entries (call them HoursX and HoursExtX). The row should be dropped if any of these are true:

  • The task name (TaskX) is empty
  • The task name is undefined (optional)
  • The HoursX and the HoursExtX are zero
  • The HoursX and the HoursExtX are empty
  • Optionally if HoursX and HoursExtX are both undefined

So I need the option to generate logical statements and check for empty string and numerical zero.

2
  • The contents in the beginning of a table cell must be expandable for \multicolumn to work. Try replacing the ifthenelse test with \expandafter\ifx\csname Task#1\endcsname\@empty \expandafter\@firstoftwo\else\expandafter\@secondoftwo\fi Jan 29, 2021 at 11:10
  • @PhelypeOleinik Thanks for the hint but this seems in my understanding to only outpu the checked value. I edited my question to make this more specific. Jan 29, 2021 at 11:59

1 Answer 1

2

You need an expandable test and \ifthenelse isn't one of them.

\documentclass{article}
\usepackage{etoolbox}
% Put some data in macros. This wil be imported later using \input{...}
\newcommand{\TaskA}{Some description comes here}
\newcommand{\TaskB}{Some other description}
\newcommand{\TaskC}{}
\newcommand{\HoursA}{1}
\newcommand{\HoursB}{3}
\newcommand{\HoursC}{0}

\newcommand{\printline}[1]{%
  \ifcsempty{Task#1}{}{#1 & \csname Task#1\endcsname & \csname Hours#1\endcsname & 42 \\}%
}

\begin{document}

\section{Correct behavior}

\begin{tabular}{|l l | c c }
A & Some description comes here & 1 & 42 \\
B & Some other description & 3 & 42 \\
\multicolumn{2}{|r|}{Sum:} & 4 & 82 \\
\end{tabular}

\section{No error}

\begin{tabular}{| l l | c c }
\printline{A}
\printline{B}
\printline{C}
\multicolumn{2}{|r|}{Sum:} & 4 & 82 \\
\end{tabular}

\end{document}

enter image description here

A higher level implementation where we also check whether \Task#1 is undefined, so you don't need to, say, define \TaskC to empty.

\documentclass{article}


% Put some data in macros. This wil be imported later using \input{...}
\newcommand{\TaskA}{Some description comes here}
\newcommand{\TaskB}{Some other description}
\newcommand{\HoursA}{1}
\newcommand{\HoursB}{3}
\newcommand{\HoursC}{0}

\ExplSyntaxOn

\prg_generate_conditional_variant:Nnn \tl_if_blank:n { v } { p,T,F,TF }

\NewExpandableDocumentCommand{\printline}{m}
 {
  \bool_lazy_and:nnT
   { \tl_if_exist_p:c { Task#1 } } % \Task#1 exists
   { ! \tl_if_blank_p:v { Task#1 } } % \Task#1 is not empty
   { #1 & \csname Task#1\endcsname & \csname Hours#1\endcsname & 42 \\}
 }

\ExplSyntaxOff

\begin{document}

\section{Correct behavior}

\begin{tabular}{|l l | c c }
A & Some description comes here & 1 & 42 \\
B & Some other description & 3 & 42 \\
\multicolumn{2}{|r|}{Sum:} & 4 & 82 \\
\end{tabular}

\section{No error}

\begin{tabular}{| l l | c c }
\printline{A}
\printline{B}
\printline{C}
\multicolumn{2}{|r|}{Sum:} & 4 & 82 \\
\end{tabular}

\end{document}
1
  • Thank you for the answer. I have never heard of these macros with underscores. I will have to get a hold of them before I can see if they will work in my case. I added a few comments on my question to clarify what I need exactly. Jan 29, 2021 at 12:02

You must log in to answer this question.

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