Fusion de cellules

LaTeX ne connaît pas de véritable « fusion de cellules ». Ouvrez latex.ltx et vous verrez que la commande horizontale, \multicolumn, commence par \multispan, c’est-à-dire par la primitive \omit de TeX — une instruction qui jette le gabarit de colonne de cette cellule. Rien n’est collé aux voisines : le modèle déclaré est ignoré et la largeur prise d’autorité. La commande verticale, \multirow, va plus loin encore : elle se contente de composer le texte dans une boîte assez haute pour retomber sur les lignes du dessous. Ces deux implémentations expliquent presque tous les faux pas de cette page, de l’erreur ! Misplaced \omit. au texte imprimé par-dessus la ligne suivante. En chemin, nous examinons le point réellement délicat : tracer un filet sous une cellule fusionnée avec \cline et \cmidrule.

Fusionner des colonnes — \multicolumn, et pourquoi il doit ouvrir une cellule

La forme est le \multicolumn{n}{spec}{text} à trois arguments : n est le nombre de colonnes couvertes, spec la spécification de l’unique cellule résultante, et text son contenu. Intégré à LaTeX standard, il ne demande aucun package. Le point crucial est que spec décrit une seule colonne fusionnée et n’hérite pas des n spécifications d’origine : il faut donc y écrire exactement l’un de l, c ou r. En écrire deux, comme dans \multicolumn{2}{cc}{…}, casse tout avec ! Missing \endgroup inserted. puis ! Extra alignment tab has been changed to \cr.. À l’inverse, spec peut porter un filet vertical | ou un @{…}, qui remplacent filets et espace inter-colonnes pour cette seule cellule fusionnée.

\multicolumn doit venir en tout premier dans une cellule. Appelé après autre chose, comme dans X \multicolumn{1}{c}{Y} & Z, il produit ! Misplaced \omit.. Comme signalé plus haut, \multicolumn est en réalité \omit, la primitive qui déclare « ne pas utiliser le gabarit de cette cellule » — et une telle déclaration n’a de sens qu’avant que la cellule ait commencé. Voilà pourquoi l’erreur arrive sous le nom \omit et non \multicolumn.

latex
\begin{tabular}{lcc}
  \hline
  \multicolumn{3}{c}{Sales summary} \\
  \hline
  Item & H1 & H2 \\
  \hline
  Domestic & 120 & 145 \\
  Overseas & 80  & 96  \\
  \hline
\end{tabular}

La première ligne replie ce qui serait trois colonnes en une cellule centrée avec \multicolumn{3}{c}{Sales summary}, servant de titre au tableau entier. Même dans une ligne fusionnée, les cellules doivent toujours totaliser le nombre de colonnes déclaré ; ici \multicolumn{3}{…} couvre les trois, donc aucun & n’est nécessaire. À retenir aussi : l’idiome avec n égal à 1. Il ne couvre rien, mais il peut remplacer l’alignement de cette seule cellule ou supprimer le filet vertical | à cet endroit. Pour centrer seulement l’en-tête d’une colonne numérique (r), écrivez \multicolumn{1}{c}{Header} ; pour supprimer le filet d’une seule cellule dans un tableau encadré, il suffit d’omettre | dans spec.

Lorsque deux cellules \multicolumn se suivent dans un tableau encadré, n’écrivez le filet vertical que dans l’une des deux. Faites suivre \multicolumn{2}{|c|}{left} d’un \multicolumn{2}{|c|}{right} et deux filets se superposent à la frontière, si bien que celui-là paraît nettement plus épais que les autres — augmentez \arrayrulewidth et cela saute aux yeux. La forme correcte supprime la barre initiale du second : \multicolumn{2}{c|}{right}. C’est un effet de bord de l’implémentation minimale : \multicolumn trace exactement ce que vous avez écrit à la place du gabarit qu’il a jeté, sans faire le ménage des doublons.

Fusionner des lignes — le package multirow et ses arguments

Une cellule couvrant plusieurs lignes ne se fait pas avec une commande standard : il faut charger le package multirow (TeX Live 2024 fournit la v2.8 du 15 mars 2021). Si vous l’oubliez, vous obtenez simplement ! Undefined control sequence.. La forme complète comporte six emplacements — \multirow[vpos]{nrows}[bigstruts]{width}[vmove]{text} — dont seuls nrows, width et text sont obligatoires : le nombre de lignes couvertes, la largeur de la cellule et son contenu. Avec * comme largeur, le texte est composé à sa largeur naturelle, ce qui fait de \multirow{3}{*}{Label} la forme la plus directe.

La règle décisive est de laisser vides les cellules situées en dessous. Placez \multirow dans la ligne du haut et, dans les lignes suivantes, passez cette colonne avec un simple &. Selon la documentation officielle : laissez les autres lignes vides dans cette colonne, « otherwise the stuff created by \multirow will over-write it ». Si vous y écrivez un contenu réel, aucune erreur n’apparaît : les deux textes sont simplement imprimés l’un sur l’autre. nrows peut aussi être négatif : une valeur positive couvre « cette ligne et les n−1 lignes dessous », une valeur négative « cette ligne et les |n|−1 lignes dessus », soit le même nombre de lignes dans les deux cas — la seule différence est d’écrire la commande dans la ligne du haut ou dans celle du bas. Les valeurs fractionnaires sont admises, donc \multirow{2.5}{*}{…} peut affiner la hauteur.

document.tex
\usepackage{multirow}
% ...
\begin{tabular}{|l|l|c|}
  \hline
  \multirow{2}{*}{Fruit}     & Apple  & 380 \\
                             & Orange & 120 \\
  \hline
  \multirow{2}{*}{Vegetable} & Carrot & 90  \\
                             & Radish & 150 \\
  \hline
\end{tabular}
ArgumentRôleRemarques
[vpos]Alignement vertical (optionnel, en tête)Par défaut c ; aussi t / b
nrowsNombre de lignes couvertes (obligatoire)Positif vers le bas, négatif vers le haut ; fractions admises
[bigstruts]Nombre d’utilisations de bigstrut couvertes (optionnel)Par défaut 0 ; préfixe t / b / tb pour affiner
widthLargeur de cellule (obligatoire)* largeur naturelle, = largeur de la colonne, une longueur donne une parbox
[vmove]Réglage fin de position (optionnel, avant text)Positif monte, négatif descend
\multirowsetupCrochet développé juste avant textInitialement \raggedright ; à changer avec renewcommand

Donnez à width une longueur absolue plutôt que *\multirow{2}{4em}{…} — et le contenu est composé en parbox de cette largeur, de sorte qu’un long libellé se replie. Sous cette forme, vous remarquerez peut-être que le texte sort au fer à gauche et non justifié. Ce n’est pas un défaut mais un choix : le crochet \multirowsetup, développé juste avant text, contient initialement \raggedright. Pour centrer, écrivez plutôt \renewcommand{\multirowsetup}{\centering}. Enfin, width accepte une valeur supplémentaire, =, qui signifie « utiliser la largeur définie pour la colonne où se trouve l’entrée » — pratique dans une colonne p{} ou une colonne X de tabularx, mais donnant un résultat étrangement large dans une colonne sans largeur définie.

\multirow ne réserve pas de place — quand le texte déborde sur les lignes suivantes

C’est l’accident le plus célèbre avec \multirow. Il ne fait pas réserver au tableau l’espace vertical dont il a besoin. La hauteur de sa boîte n’est qu’estimée à partir de nrows et bigstruts, car il ignore la hauteur réelle des lignes. Si le contenu forme une boîte haute, il déborde donc simplement sur les lignes du dessous ou sous le bas du tableau. La documentation officielle le dit franchement, avec pour exemple un tableau d’effets secondaires où deux entrées \multirow « are too high; the first sticks out into the second entry, and the second one sticks out of the table ». Le symptôme apparaît dès que nrows est trop petit pour la quantité de contenu.

Il existe trois remèdes, dont les deux premiers figurent dans la documentation officielle. D’abord, ajouter des lignes vides pour couvrir le chevauchement : écrivez autant de & & \\ qu’il en manque. C’est la voie la plus sûre et il suffit de compter les lignes. Ensuite, étirer les lignes elles-mêmes : placez dans chacune un étai de largeur nulle comme \newcommand{\mystrut}{\rule[-8pt]{0pt}{20pt}} pour gagner de la hauteur. (On peut aussi utiliser \bigstrut du package bigstrut et déclarer leur nombre dans [bigstruts].) Enfin, déclarer un nrows plus grand que la réalité, éventuellement fractionnaire : le plus rapide, mais cela dérègle facilement le rapport aux filets, donc à garder en dernier recours.

document.tex
\usepackage{multirow}
% ...
% the label wraps to four lines but the block has only two rows,
% so raise nrows to 4 and add two empty rows to cover the overlap
\begin{tabular}{|l|c|}
  \hline
  \multirow{4}{4em}{A long label that wraps} & one \\
                                             & two \\
                                             &     \\
                                             &     \\
  \hline
  next & row \\
  \hline
\end{tabular}

La même faiblesse — ignorer les hauteurs de ligne — se manifeste aussi lorsqu’une ligne ailleurs dans le tableau est anormalement haute. L’exemple de la documentation est un tableau dont la troisième ligne se replie dans une colonne p{4cm}, si bien que \multirow{3}*{Week 38} se retrouve au-dessus du centre visuel du bloc. Quand les lignes ne sont pas de même hauteur, le centre estimé par \multirow et celui que voit l’œil ne coïncident pas. On corrige ces décalages à la main avec un petit [vmove]. Employer une unité relative comme .1ex donne à la correction une bonne chance de survivre à un changement ultérieur de corps du texte — conseil lui aussi tiré de la documentation officielle.

Quand un filet rencontre une cellule fusionnée — \cline et \cmidrule, pas \hline

C’est le point le plus délicat de tout le sujet. Écrivez \hline entre des lignes couvertes par un \multirow et le filet est tracé en plein dans le texte de la cellule fusionnée — le libellé paraît barré, car \hline se contente de poser une \hrule sur toute la largeur du tableau entre deux lignes, sans rien savoir de ce qui se trouve au-dessus. Augmentez \arrayrulewidth et l’on voit nettement les lettres transpercées. Le remède est simple : exclure cette colonne du filet — avec une plage de colonnes, \cline{2-3} en LaTeX standard, ou \cmidrule{2-3} avec booktabs.

document.tex
\usepackage{multirow}
% ...
% \hline here would draw straight through the word "Group";
% \cline{2-3} spares column 1
\begin{tabular}{|l|l|c|}
  \hline
  \multirow{2}{*}{Group} & alpha & 1 \\
  \cline{2-3}
                         & beta  & 2 \\
  \hline
\end{tabular}

\cline et \cmidrule acceptent tous deux une plage de colonnes, mais ont un caractère différent. \cline{i-j} a l’épaisseur \arrayrulewidth (0,4 pt par défaut) et va exactement d’un bord à l’autre des colonnes indiquées, si bien que deux \cline voisins se rejoignent et se lisent comme un seul. Le \cmidrule{i-j} de booktabs est plus fin — \cmidrulewidth, 0,03 em par défaut, environ 0,3 pt pour un corps de 10 pt — et prend \aboverulesep et \belowrulesep d’espace au-dessus et au-dessous. Plus important en pratique, un argument optionnel entre parenthèses rogne ses extrémités : \cmidrule(lr){2-3} le raccourcit des deux côtés, de sorte qu’un blanc s’ouvre entre lui et le \cmidrule voisin, et que les deux se lisent comme des filets distincts — l’usage courant quand plusieurs groupes d’en-tête se suivent.

latex
\usepackage{booktabs}
% ...
% two \multicolumn headers, each underlined by its own trimmed rule
\begin{tabular}{lcccc}
  \toprule
       & \multicolumn{2}{c}{2024} & \multicolumn{2}{c}{2025} \\
  \cmidrule(lr){2-3} \cmidrule(lr){4-5}
  Item & Q1 & Q2 & Q1 & Q2 \\
  \midrule
  Apple & 1 & 2 & 3 & 4 \\
  \bottomrule
\end{tabular}

C’est la forme de travail standard lorsqu’on combine \multicolumn et filets. \multicolumn{2}{c}{2024} crée un titre sur deux colonnes, et le \cmidrule(lr){2-3} juste en dessous dit « ces deux-là vont ensemble ». Sans le (lr), les deux filets se rejoignent et la frontière entre groupes disparaît. Si l’on veut vraiment deux \cmidrule empilés sur la même plage de colonnes, il faut intercaler \morecmidrules de booktabs : écrits simplement à la suite, deux \cmidrule sont considérés comme appartenant à la même rangée de filets. Dans les tableaux colorés, un \cline peut disparaître sous le fond ; ce symptôme et le contournement par hhline sont traités dans la page « Colorer un tableau ».

Fusionner un bloc rectangulaire — \multirow à l’intérieur de \multicolumn

Un bloc rectangulaire couvrant les deux directions se construit en combinant \multirow et \multicolumn. L’ordre est fixe : placez \multirow dans \multicolumn. La documentation officielle donne \multicolumn{2}{c}{\multirow{3}{*}{Multi-multi}} en exemple et précise que l’imbrication inverse « will not work ». Retenez : le \multicolumn extérieur porte l’étendue horizontale, le \multirow intérieur la verticale. Et la règle de \multirow reste valable ici : la même position dans les lignes du dessous conserve la forme du \multicolumn mais reste vide de contenu.

document.tex
\usepackage{multirow}
% ...
\begin{tabular}{|l|l|c|}
  \hline
  \multicolumn{2}{|c|}{\multirow{2}{*}{Region and class}} & Count \\
  \multicolumn{2}{|c|}{}                                  &       \\
  \hline
  East & Kanto  & 12 \\
  \cline{1-3}
  West & Kansai & 9  \\
  \hline
\end{tabular}

Couper des lignes dans une cellule n’est pas fusionner — makecell

Une distinction s’impose ici. Vouloir couper une seule cellule sur plusieurs lignes n’est pas une fusion. Comme les colonnes l, c et r ne se replient pas, on est tenté d’écrire \\ directement dans une cellule — mais cela casse silencieusement le tableau, sans erreur : avec A & B\\C \\, TeX lit le \\ comme une fin de ligne et compose C en première cellule de la ligne suivante. C’est justement l’absence d’erreur qui rend ce cas plus pénible. Pour couper simplement une courte chaîne à l’endroit voulu, \makecell{…} du package makecell est l’outil le plus commode.

\makecell{line1\\line2} compose son contenu comme un petit tabular à une colonne, ce qui explique que \\ y serve de saut de ligne forcé. Un argument optionnel règle l’alignement — \makecell[l]{…} au fer à gauche, \makecell[t]{…} en haut — en passant une lettre pour l’alignement vertical et une pour l’horizontal (les deux centrés par défaut). Pour les en-têtes, il existe aussi \thead{…}, avec police et espacements communs. Si le contenu est long et doit se replier automatiquement selon une largeur, la bonne solution est une colonne p{width}, ou m{width} d’array pour le centrage vertical, et non \makecell.

document.tex
\usepackage{makecell}
% ...
\begin{tabular}{lc}
  \hline
  \thead{Item} & \thead{Year on year\\(\%)} \\
  \hline
  Revenue & \makecell[r]{+8.2\\(record high)} \\
  \hline
\end{tabular}

Quel outil choisir, et quand

Le choix est simple : \multicolumn pour couvrir des colonnes, \multirow pour couvrir des lignes, les deux pour un rectangle (avec \multirow à l’intérieur), et \makecell seulement pour couper des lignes dans une cellule. Si vous voulez replier un long texte sur une largeur, aucun de ces outils n’est la réponse : c’est l’affaire d’une colonne p{width}. Et une fois écrit un tableau comportant des fusions, regardez toujours le PDF et vérifiez trois points : avez-vous oublié de vider une cellule sous un \multirow (du texte se superpose-t-il ?), la boîte du \multirow déborde-t-elle sous le bloc (augmentez nrows ou ajoutez une ligne vide), et un filet traverse-t-il une cellule fusionnée (remplacez \hline par \cline ou \cmidrule) ? Ces trois contrôles couvrent presque tous les accidents réels.