2

When creating table headings, a 1-cell \multicolumn is often used. To simplify this, one might make a table-head macro:

% this definition works, but doesn't allow controlling alignment
\newcommand{\Th}[1]{\multicolumn{1}{l}{\textbf{#1}}}

However, we might not always want a left-aligned column; sometimes it might be more appropriate to right-align or center, etc. However, it’s very difficult to add an optional argument controlling the column specification:

\newcommand{\Th}[2][l]{\multicolumn{1}{#1}{\textbf{#2}}}
% when used: ! Misplaced \omit.
% \multispan ->\omit
%                    \@multispan
% l.8     \Th{Header}
%                     & \Th[r]{header (\textsc{usd})} & \Th{header} \\

Below are some ideas I had for potential solutions; the error messages they create are above the definition. What am I missing here?

This answer to “re-using column specifications in tabular” implies that solution #3 — which temporarily creates a new column-type and uses it — should work, but it still creates an error.

I’m also aware that the makecell package provides a partial solution via its \thead macro, but it’s not granularly-configurable enough — and I would like to know why these definitions don’t work either way.

\documentclass{article}
\usepackage{array}
\makeatletter
% attempt #1: edef/expandafter solution
% when used: ! Use of \\Th doesn't match its definition.
% \text@command #1->\def \reserved@a {
%                                     #1}\ifx \reserved@a \@empty \let \check@...
% l.16 \Th{Header}
%                  & \Th{header (\textsc{usd})} & \Th{header} \\
\newcommand{\Th}[2][l]{%
  \edef\@multicolumncontents{{1}{#1}{\textbf{#2}}}%
  \expandafter\multicolumn\@multicolumncontents}

% attempt #2: expandafter/begingroup solution
% when used: ! Misplaced \omit.
% \multispan ->\omit
%                    \@multispan
% l.21 \Th{Header}
%                  & \Th[r]{header (\textsc{usd})} & \Th{header} \\
\newcommand{\Th}[2][l]{%
  \expandafter\multicolumn\begingroup{1}{#1}{\textbf{#2}}\endgroup}

% attempt #3: newcolumntype solution
% when used: ! Misplaced \omit.
% \multispan ->\omit
%                    \@multispan
% l.31 \Th{Header}
%                  & \Th[r]{header (\textsc{usd})} & \Th{header} \\
\newcommand{\Th}[2][l]{%
  \newcolumntype\@thcol{#1}%
  \multicolumn{1}{\@thcol}{\textbf{#2}}}
\makeatother

\begin{document}
\begin{tabular}{rrr}
\Th{Header} & \Th[r]{header (\textsc{usd})} & \Th{header} \\
data        & 12831                      & data \\
1238        & 12.38                      & 4893258439 \\
$\delta$    & 10                         & 1238 \\
\end{tabular}
\end{document}
4

This is due to the fact that \multicolumn has to be “the first thing” after & or at the beginning of a row.

No unexpandable instructions can intervene and a command defined with \newcommand to have an optional argument uses \@ifnextchar in order to determine whether [ follows, which eventually requires the unexpandable \futurelet, much earlier than the replacement text is inserted.

There is a very easy solution: use xparse that can define expandable commands with optional arguments, provided a mandatory one trails.

\documentclass{article}
\usepackage{xparse}

\NewExpandableDocumentCommand{\Th}{O{l}m}{\multicolumn{1}{#1}{\textbf{#2}}}

\begin{document}

\begin{tabular}{rrr}
\Th{Header} & \Th[r]{header (\textit{usd})} & \Th{header} \\
data        & 12831                      & data \\
1238        & 12.38                      & 4893258439 \\
$\delta$    & 10                         & 1238 \\
\end{tabular}

\end{document}

enter image description here

3

When you use a \multicolumn in your tabular, the implementation achieves the desired effect by a combination of the two TeX primitives \omit, to remove the cell's column format, and \span, to "merge" two column cells into one. However, there's a restriction: If \omit occurs in a cell, it has to be the very first unexpandable token.

In your \Th version without an optional argument this is fine because there's only fully expandable commands involved here which finally results in \omit actually being the first unexpandable token. On the other hand, the version with an optional argument uses definitions and assignments internally which are not expandable and thus make \omit appear somewhere later in the token stream, hence the Misplaced \omit error.

So the trick is to rewrite \Th in a way that makes it full expandable up to the point where \multicolumn comes into play:

\documentclass{article}
\usepackage{array}

\makeatletter
\def\Th#1#{%
    \if\relax\detokenize{#1}\relax
        \expandafter\Th@@\expandafter l%
    \else
        \Th@#1%
    \fi
}
\def\Th@[#1]\fi{\fi\Th@@{#1}}
\def\Th@@#1#2{\multicolumn{1}{#1}{\textbf{#2}}}
\makeatother

\begin{document}
\begin{tabular}{rrr}
\Th{Left} & \Th[c]{\textit{Center}} & \Th[r]{Right} \\
xxxxxxxxxxxxxx & xxxxxxxxxxxxxx & xxxxxxxxxxxxxx \\
xxxx & xxxx & xxxx \\
xxxxxxx & xxxxxxx & xxxxxxx \\
\end{tabular}
\end{document}

enter image description here

\Th reads anything up until the first { token and checks whether the part between \Thand { is empty. If so, \Th@@ is called with l as the default alignment parameter. Otherwise we parse the optional parameter via \Th@ and call \Th@@ with the passed alignment parameter.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.