6

I was preparing some exercises with tables for beginners, without resorting to additional packages.

I found this anomaly in a multi-column tabular that distilled to its simplest is

\documentclass{article}

\begin{document}

\section{Wrong}

\begin{tabular}{|c|*{12}{c|}} \hline x2 col & \multicolumn{2}{c|}{1x2a} & \multicolumn{2}{c|}{1x2b} & \multicolumn{2}{c|}{1x2c} & \multicolumn{2}{c|}{1x2d} & \multicolumn{2}{c|}{1x2e} & \multicolumn{2}{c|}{1x2f}\ \hline x3 col & \multicolumn{3}{c|}{1x3a} & \multicolumn{3}{c|}{1x3b} & \multicolumn{3}{c|}{1x3c} & \multicolumn{3}{c|}{1x3d} \ \hline \end{tabular}%

\section{Right}

\begin{tabular}{|c|*{12}{c|}} \hline x2 col & \multicolumn{2}{c|}{1x2a} & \multicolumn{2}{c|}{1x2b} & \multicolumn{2}{c|}{1x2c} & \multicolumn{2}{c|}{1x2d} & \multicolumn{2}{c|}{1x2e} & \multicolumn{2}{c|}{1x2f}\ \hline x4 col & \multicolumn{4}{c|}{1x4a} & \multicolumn{4}{c|}{1x4b} & \multicolumn{4}{c|}{1x4c} \ \hline \end{tabular}

\end{document}

one

Multi-column cells \multicolumn{3}{c|}{…} in the first tabular don't span three columns; while in the second, similar, tabular works fine.

I found a recent reference on this site (resolved by adding a single empty row) but frankly I don't understand why this is happening.

I'm looking for an explanation with “predictive” powers to teach others. How can one decide a priori (before compiling) if a particular tabular needs to be corrected?

  • 2
    What is the purpose of defining 12 data columns (in addition to the header column) if you're never going to any of these columns individually? Take the second table, for example: Why define 12 data columns when defining 6 would do perfectly well: Get rid of the multicolumn{2}{c|}...} wrappers in the upper row and replace the \multicolumn{4}{c|}{...} with \multicolumn{2}{c|}{...} directives in the secod row. – Mico Feb 02 '23 at 20:06
  • It probably gets confused by the lack of 'normal' cells (i.e. without \multicolumn). If you add a normal row, like 1 & 2 & 3 & 4 & 5 & 6 & 7 & 8 & 9 & 10 & 11 & 12 & 13 \\\ it works. – Pieter van Oostrum Feb 02 '23 at 20:33
  • @PietervanOostrum - In the first table, I'd say it's not so much a case of confusion as of under-determination: The OP simply isn't giving LaTeX enough information to figure out where to draw two of the three column dividers in row x3. – Mico Feb 02 '23 at 20:47

4 Answers4

7

What you label an "anomaly", others may view as user error.

  • The structure you provide for the first table, which you label "wrong", is insufficient, in the sense that you don't give LaTeX enough information to determine properly where to set the column boundaries in the x3 row. Do check out the screen shot below and notice what happens if one adds an x1 row, with dummy contents for each of the 12 data cells: Now LaTeX does have enough information to determine where to draw the column boundaries in row x3.

  • The second table, which you label "right", happens to work -- but only by shere luck. Instead of defining 12 data columns and providing 6 \multicolumn{2}{c|}{...} directives in row x2 and 3 \multicolumn{4}{c|}{...} directives in row x4, why not define just 6 data columns, get rid of the \multicolumn{2}{c|} wrappers in row x2, and replace all instances of \multicolumn{4}{c|} in row x4 with \multicolumn{2}{c|}?

enter image description here

\documentclass{article}
\usepackage{array}
\newcommand\mc[2]{\multicolumn{#1}{c|}{#2}} % handy shortcut macro

\begin{document}

\section{Wrong}

\begin{tabular}{|c|*{12}{c|}} \hline x2 row & \mc{2}{1x2a} & \mc{2}{1x2b} & \mc{2}{1x2c} & \mc{2}{1x2d} & \mc{2}{1x2e} & \mc{2}{1x2f}\ \hline x3 row & \mc{3}{1x3a} & \mc{3}{1x3b} & \mc{3}{1x3c} & \mc{3}{1x3d} \ \hline \end{tabular}

\smallskip\noindent \begin{tabular}{|c|*{12}{c|}} \hline x1 row & . & . & . & . & . & . & . & . & . & . & . & . \ \hline x2 row & \mc{2}{1x2a} & \mc{2}{1x2b} & \mc{2}{1x2c} & \mc{2}{1x2d} & \mc{2}{1x2e} & \mc{2}{1x2f}\ \hline x3 row & \mc{3}{1x3a} & \mc{3}{1x3b} & \mc{3}{1x3c} & \mc{3}{1x3d} \ \hline \end{tabular}

\section{Right (really?)}

\begin{tabular}{|c|*{12}{c|}} \hline x2 row & \mc{2}{1x2a} & \mc{2}{1x2b} & \mc{2}{1x2c} & \mc{2}{1x2d} & \mc{2}{1x2e} & \mc{2}{1x2f}\ \hline x4 row & \mc{4}{1x4a} & \mc{4}{1x4b} & \mc{4}{1x4c} \
\hline \end{tabular}

\smallskip\noindent \begin{tabular}{|c|*{6}{c|}} \hline x1 row & 1x2a & 1x2b & 1x2c & 1x2d & 1x2e & 1x2f \ \hline x2 row & \mc{2}{1x4a} & \mc{2}{1x4b} & \mc{2}{1x4c} \
\hline \end{tabular}

\end{document}


Addendum to address the OP's follow-up question. To understand better the claim I made above, about the OP's tabular environments being underdetermined, consider the following simplified versions of the OP's first tabular environment (I've left off the header column and data columns 7 thru 12):

\documentclass{article}
\usepackage{array} % for 'w' column type
\begin{document}
\begin{tabular}{|*{6}{p{100in}|}}
\hline
\multicolumn{2}{|c|}{wwww} & \multicolumn{2}{c|}{bbbb} & \multicolumn{2}{c|}{cccc} \\ 
\hline
\multicolumn{3}{|c|}{dddd} & \multicolumn{3}{c|}{eeee}\\ 
\hline
\end{tabular}

\begin{tabular}{|*{60}{wc{50cm}|}} \hline \multicolumn{20}{|c|}{wwww} & \multicolumn{20}{c|}{bbbb} & \multicolumn{20}{c|}{cccc} \ \hline \multicolumn{30}{|c|}{iiii} & \multicolumn{30}{c|}{zzzz}\ \hline \end{tabular} \end{document}

enter image description here

  • Observe that the first tabular environment is defined to possess 6 columns, each notionally 100 inches or about 2.5 meters wide [!]. Not to fear: The tabular environment is not more than 15 meters wide. Whew! What's going on?

    • First, observe that there's not a single cell that's one column wide. (In a way, that's a good thing, since such a cell would be 100" wide by construction...)

    • Second, observe that the widths of the cells in the upper row, which are of type c (by virtue of the \multicolumn commands) are just the natural widths of the strings "wwww", "bbbb", and "cccc", respectively. And, because the letter w is wider than either b or c, the first cell in the upper row is noticeably wider than the other two. Note that the fact that the "underlying" single columns are supposed to be 100" wide each plays no role whatsoever; the only piece of information LaTeX is able to make use of is that the column type of the combined cells is c in all three cases.

    • Now on to the second row of the first table, where there are only two cells; they contain the strings "dddd" and "eeee", respectively. Again, because the column type of the combined cells is c, the first cell's width is given by the natural width of the string "dddd". Note that this is less than the width of the first cell in the upper row.

    • The width of the second cell in the lower row is given as a residual, between the overall of the tabular environment and of the natural width of the first cell in the lower row.

  • Consider now the second tabular environment. It's defined to have 60 [!] columns, each with width 50cm, for a total usable width of 30 [!!] meters. (The notional total width is even larger than the notional usable width, because of whitespace padding at the cell edges.) Again, though, the overall structure of the table is underdetermined, as there's no information to link the individual columns to the grouped \multicolumn constructs.

    • The three cells in row 1 of the second table notionally span 15, 20, and 25 "underlying" columns. But since there's no information to link the appearance of the grouped cells to any underlying single-column cell, all LateX can go by is to employ the c column type of the three grouped cells, and hence assign the cells their "natural" widths. And, because the cell contents in row 1 of the second table are the same as in row 1 of the first table, the overall width of the second table is exactly the same as that of the first table. The fact that the second table notionally contains 60 columns is simply irrelevant.

    • The first cell in the lower row of table 2 notionally contains 30 underlying columns. But that's irrelevant too, since LaTeX has no information to make use of this "fact". Indeed, even though the first cell in row 2 contains twice as many underlying rows as the first cell in row 1 (30 vs 15), its overall width is smaller because "iiii" takes up less space than "wwww".

    • The width of the second cell in the lower row is once more just a residual.

I trust that these specific examples have managed to convince you that the structure of the original tables is truly underdetermined.

Mico
  • 506,678
  • It doesn't really answer the question (why is this happening). I already know that adding a dummy row circumvents the problem.

    “the structure you provide for the first table is insufficient”.

    Please kindly point me where this is documented.

    – Amélie Th Feb 03 '23 at 13:18
  • @AmélieTh - Please see the addendum I posted. – Mico Feb 03 '23 at 17:13
5

A not so well-known fact is that when TeX is processing a table with \halign, it effectively merges columns that are spanned in all rows.

For instance, if you do

\begin{tabular}{cc}
\multicolumn{2}{c}{abc}\\
\multicolumn{2}{c}{def}
\end{tabular}

(LaTeX uses \halign under the hood), you get a one-column table.

Let's examine your “wrong” table, actually a reduced version that shows the same problem. I use \MC to avoid clutter.

\documentclass{article}

\newcommand{\MC}[2]{\multicolumn{#1}{c|}{#2}}

\begin{document}

\begin{tabular}{|c|*{6}{c|}} \hline x2 col & \MC{2}{1x2a} & \MC{2}{1x2b} & \MC{2}{1x2c} \ \hline x3 col & \MC{3}{1x3a} & \MC{3}{1x3b} \ \hline \end{tabular}

\end{document}

enter image description here

You probably expected that the second and third cells in the second row span one and a half cell in the first row. Sorry, no.

It's a bit complicated to explain why you get that output, because of the interaction of \multicolumn with the column merging done by TeX. And, indeed, if you add a “dummy” row

\documentclass{article}

\newcommand{\MC}[2]{\multicolumn{#1}{c|}{#2}}

\begin{document}

\begin{tabular}{|c|*{6}{c|}} \hline x2 col & \MC{2}{1x2a} & \MC{2}{1x2b} & \MC{2}{1x2c} \ \hline x3 col & \MC{3}{1x3a} & \MC{3}{1x3b} \ \hline \multicolumn{1}{c}{}& \multicolumn{1}{c}{}& \multicolumn{1}{c}{}& \multicolumn{1}{c}{}& \multicolumn{1}{c}{}& \multicolumn{1}{c}{}& \multicolumn{1}{c}{} \end{tabular}

\end{document}

you get

enter image description here

Well, not the expected output either. Why? Because of \tabcolsep spaces that are the same in all cases, but there's fewer of them in the second row. The missing or excess space is compensated in the last column.

\documentclass{article}

\newcommand{\MC}[2]{\multicolumn{#1}{c|}{#2}}

\begin{document}

\begin{tabular}{|c|{6}{c|}} \hline x1 & \MC{2}{1x2a} & \MC{2}{1x2b} & \MC{2}{1x2c} \ \hline x2 & \MC{3}{\hspace{1.33333\tabcolsep}1x3a\hspace*{1.33333\tabcolsep}} & \MC{3}{1x3b} \ \hline \multicolumn{1}{c}{}& \multicolumn{1}{c}{}& \multicolumn{1}{c}{}& \multicolumn{1}{c}{}& \multicolumn{1}{c}{}& \multicolumn{1}{c}{}& \multicolumn{1}{c}{} \end{tabular}

\end{document}

Adding the missing spaces makes the result as perhaps expected.

enter image description here

Definitely not for beginners. And the fact that such tables can be obtained with other tools doesn't make them good.

egreg
  • 1,121,712
  • Thank you for your kind answer.

    Are you suggesting that every table that uses multiple columns should have at least one row of individual cells, dummy (and the tabsep correction!) if necessary?

    Is this a documented feature?

    – Amélie Th Feb 03 '23 at 13:19
  • 3
    @AmélieTh No, I'm suggesting that such tables are bad. :-) – egreg Feb 03 '23 at 13:33
1

With tabularray package

\documentclass[12pt,oneside]{book}

\usepackage{tabularx, } \usepackage{tabularray}

\begin{document}

    \begin{tblr}{
    hlines={1.5pt},
    vlines={1.5pt},
    cell{1}{2,4,6,8,10,12} = {c=2}{c}, % multicolumn
    cell{2}{2,6,10} = {c=4}{c}, % multicolumn
    }

x2 col
& 1x2a & & 1x2b & & 1x2c & &1x2d & &1x2e & & 1x2f & \

x4 col    
    &1x4a   
        &&&      
            &1x4b
                &&&      
                    & 1x4c
                        &&& 
                        \\

\end{tblr}



\end{document}

enter image description here

js bibra
  • 21,280
0

Visual explanation: (the first one is "result with proper padding", the last one is your original "wrong" result)

You can easily see why as the padding tends to 0, the columns become "merged", regardless of whether TeX's internal implementation of \halign processes the columns together or not.

output

The faint red lines are added for visualization.

\documentclass{article}
\usepackage{xcolor}
\begin{document}

% approach taken from https://tex.stackexchange.com/a/402428/250119 to ensure minimum row width, with modifications

\newcommand\specialpadding[1]{% \omit % TeX primitive, read e.g. TeXbook for details... \textcolor{red!20}{% \smash{\rlap{% \hspace{-.2pt}% correct positioning for the faint red line, we start from halfway to the right of the rule and the default arrayrulewidth is 0.4pt \rule[-25.2pt]{.4pt}{25.2pt}% the faint red line }% }}% \hspace{#1}% the padding itself } % miscellaneous note, the command above must not be protected/robust

\newcommand\testtable[1]{ \begin{tabular}{|c|*{12}{c|}} \specialpadding{#1}& \specialpadding{#1}& \specialpadding{#1}& \specialpadding{#1}& \specialpadding{#1}& \specialpadding{#1}& \specialpadding{#1}& \specialpadding{#1}& \specialpadding{#1}& \specialpadding{#1}& \specialpadding{#1}& \specialpadding{#1}& \specialpadding{#1} \ \hline x2 col & \multicolumn{2}{c|}{1x2a} & \multicolumn{2}{c|}{1x2b} & \multicolumn{2}{c|}{1x2c} & \multicolumn{2}{c|}{1x2d} & \multicolumn{2}{c|}{1x2e} & \multicolumn{2}{c|}{1x2f}\ \hline x3 col & \multicolumn{3}{c|}{1x3a} & \multicolumn{3}{c|}{1x3b} & \multicolumn{3}{c|}{1x3c} & \multicolumn{3}{c|}{1x3d} \ \hline \end{tabular}

\vspace{0.8cm} }

\testtable{0.53cm} \testtable{0.3cm} \testtable{0.1cm} \testtable{0cm}

\end{document}

If you throw away the \textcolor{red!20}{...} part, you automatically get a solution that adds some "invisible" padding.


An alternative, but more "understandable" solution, is to specify explicit width.

(refer to How to create fixed width table columns with text raggedright/centered/raggedleft? for how to center in p-type column)

\documentclass{article}
\begin{document}

\begin{tabular}{|c|*{12}{c|}} \hline x2 col & \multicolumn{2}{p{23.6pt}|}{1x2a} & \multicolumn{2}{p{23.6pt}|}{1x2b} & \multicolumn{2}{p{23.6pt}|}{1x2c} & \multicolumn{2}{p{23.6pt}|}{1x2d} & \multicolumn{2}{p{23.6pt}|}{1x2e} & \multicolumn{2}{p{23.6pt}|}{1x2f}\ \hline x3 col & \multicolumn{3}{p{41.6pt}|}{\centering 1x3a} & \multicolumn{3}{p{41.6pt}|}{\centering 1x3b} & \multicolumn{3}{p{41.6pt}|}{\centering 1x3c} & \multicolumn{3}{p{41.6pt}|}{\centering 1x3d} \ \hline \end{tabular}

\end{document}

note that if I calculated correctly, 2\tabcolsep+\arrayrulewidth is added to the width of each such column, which is why I specified the width to be 23.6pt and 41.6pt respectively -- the actual widths are 36pt and 54pt.

output

user202729
  • 7,143
  • Given that the "intended" solution in this case is probably to evenly divide the width of the 6 merged cells in the first row into two for 2 merged cells in the second row, maybe tabularray can automatically do this, although I haven't tested this. – user202729 Feb 04 '23 at 01:02