Dernière colonne de tableau centrée

Bonjour,
J'aimerais faire un tableau avec des largeurs de colonnes imposées et des textes centrés dans les cellules. Mais quand je fais
\documentclass{article}
\usepackage{colortbl}
\begin{document}

\begin{tabular}{|m{2cm}|m{2cm}|}
\centering a & \centering b\\
\hline
\centering a & \centering b\\
\end{tabular}

\end{document}
j'ai une erreur (et la deuxième ligne commence à l'intérieur de la première, c'est n'importe quoi), et quand je fais
\begin{tabular}{|m{2cm}|m{2cm}|}
\centering a & [b][color=#FF0000]{[/color][/b]\centering b[b][color=#FF0000]}[/color][/b]\\
\hline
\centering a & \centering b\\
\end{tabular}
le texte de la cellule en haut à droite n'est pas centré. Pour les autres cellules pas de problème ; ce sont juste les cellules de droites sauf la dernière que je n'arrive pas à centrer. Savez-vous comment résoudre le problème ?
Merci d'avance

Réponses

  • Bonsoir Calli,

    Je commence par ton premier bout de code. Il produit l'errreur suivante :
    ERROR: Misplaced \noalign.
    
    --- TeX said ---
    \hline ->\noalign 
                      {\ifnum 0=`}\fi \let \hskip \vskip \let \vrule \hrule \let...l.7 \hline
    
    En effet, la macro \centering redéfinit \\ (voir la fin de mon message), donc après '\centering b\\', TeX est toujours en train de lire le contenu de la cellule (1,2) de ton tableau. Il trouve alors la macro \hline. Il la développe, le texte de remplacement commence par \noalign, il exécute \noalign (une primitive TeX)... et boum ! Comme le dit le fichier .log :
    I expect to see \noalign only after the \cr of an alignment.

    \noalign n'est valide qu'après \cr, c'est-à-dire soit avant la première ligne d'un tableau, soit après une ligne dûment terminée (\cr est une des deux primitives TeX pour terminer une ligne de tableau TeX, ainsi que le préambule d'un tel tableau ; le \\ des tableaux LaTeX s'appuie dessus ou sur sa copine \crcr).

    \noalign sert à insérer du matériel (ou matériau ?) vertical aux endroits en question. Exemple (qui pourrait être compilé avec TeX en enlevant \documentclass, etc. et en terminant par \bye) :
    \documentclass{article}
    \begin{document}
    
    \noindent aaaaaaaaaaaaaaaaaaaaaaaa\par
    \halign{x#y&z#t\cr
      \noalign{\hrule}
      1&a\cr
      \noalign{\hrule\vskip 10pt\hrule}
      2&b\cr
      \noalign{\hrule}}
    
    \end{document}
    
    Tu noteras sur ma capture d'écran l'absence d'interligne autour des '\hrule' produites par notre tableau \halign : c'est dû à une règle spéciale de TeX concernant les “rules” (une règle qui concerne les règles, quoi (:P)) :
    TeX does not put interline glue between rule boxes and their neighbors in a vertical list

    Fin de la digression sur \noalign. Lorsque tu écris :
    j'ai une erreur (et la deuxième ligne commence à l'intérieur de la première, c'est n'importe quoi)
    effectivement, ça peut être n'importe quoi. Il y a une règle générale en (La)TeX : lorsque la compilation signale des erreurs, il est inutile de raisonner sur la sortie DVI ou PDF : comme il y a eu des erreurs, il n'y a aucune « garantie » concernant la sortie. Je ne regarde même pas le PDF dans ces cas-là : il faut d'abord corriger les erreurs. Les warnings tels que “Overfull \hbox” ne rentrent pas dans cette catégorie : ce sont des warnings, pas des erreurs.

    Passons à ton deuxième essai :
    \begin{tabular}{|m{2cm}|m{2cm}|}
    \centering a & {\centering b}\\
    \hline
    \centering a & \centering b\\
    \end{tabular}
    
    La cellule (1,2) ne provoque plus d'erreur mais n'a pas le centrage horizontal. Cela découle du fait que \centering n'a plus d'effet une fois le groupe fermé, car elle ne fait que des affectations locales. Or l'effet recherché ne se produit qu'en fin de paragraphe, i.e. après \par (la macro \\ redéfinie par \centering produit justement un token \par, entre autres). Ceci ne se produit jamais ici pour la cellule (1,2), d'où le résultat observé.

    Quand on a compris ce qui se passe, on trouve facilement des remèdes. Le plus proche de ton code :
    \documentclass{article}
    \usepackage{array}
    \begin{document}
    
    \begin{tabular}{|m{2cm}|m{2cm}|}
    \centering a & \centering b\tabularnewline
    \hline
    \centering a & \centering b\tabularnewline
    \end{tabular}
    
    \end{document}
    
    (j'ai remplacé 'colortbl' par 'array' car cet exemple n'utilise pas de couleurs).

    Technique légèrement différente avec du code factorisé :
    \documentclass{article}
    \usepackage{array}
    
    \begin{document}
    
    \newcolumntype{E}[1]{ >{\centering\arraybackslash} m{#1}| }
    
    \begin{tabular}{| *{2}{E{2cm}} }
    a & b\\
    \hline
    a & b\\
    \end{tabular}
    
    \end{document}
    
    \newcolumntype fonctionne comme \newcommand, c'est très facile. La syntaxe >{...} dans le préambule d'un tableau est valable grâce au \usepackage{array} et provoque l'insertion automatique de ... au début de chaque cellule de la colonne correspondante (... y joue le rôle du x ou du z de mon exemple avec \halign ; <{...} ferait jouer à ... celui de y ou de t). Enfin, \arraybackslash est une macro toute simple :
    > \arraybackslash=macro:
    ->\let \\\tabularnewline .
    
    (résultat obtenu avec \show\arraybackslash). Ici, elle annule donc l'action de \centering consistant à modifier la définition de \\ : elle fait en sorte que \\ soit identique à \tabularnewline, qui termine une ligne de tableau.

    Regardons la définition de \centering pour y voir plus clair :
    \DeclareRobustCommand\centering{%
      \let\\\@centercr
      \rightskip\@flushglue\leftskip\@flushglue
      \finalhyphendemerits=\z@
      \parindent\z@\parfillskip\z@skip}
    
    Tu vois comme la première ligne modifie (localement) \\ ?

    Tu vas peut-être me demander pourquoi les 'b' de la deuxième colonne sont centrés avec mon code, puisqu'ils ne sont suivis ni de \@centercr, ni de \par. C'est parce que les cellules des colonnes de type 'p', 'b' ou 'm' font toujours un paragraphe (c'est pour cela qu'on est obligé de donner leur largeur, aka \hsize du point de vue de TeX, car un paragaphe doit savoir quand il faut retourner à la ligne. Autrement dit, la fin de ces cellules est automatiquement une fin de paragraphe, comme le ferait un \par.

    Edit : ajout de l'extrait du TeXbook concernant la suppression automatique de l'interligne autour des “rules” en mode vertical.122988
    122990
  • Je ne comprends pas le m dans les options de colonnes.
    J'aurai écrit :
     \documentclass{article}
     \usepackage{colortbl}
     \begin{document}
     
     \begin{tabular}{|C{2cm}|C{2cm}|}
      a &  b\\
     \hline
     a &  b\\
     \end{tabular}
     
     \end{document}
    

    mais je n'ai pas testé.

    Edit : Bon ben dans le même temps, notre meilleur spécialiste est passé par là. Au passage, merci brian pour tes contributions.
  • @rémi

    Sauf si tu l'as toi-même (ou un package) défini quelque part, il n'y a pas de type de colonne 'C'. Il y a bien sûr 'c', mais ce type-là ne prend pas d'argument (il ne forme pas de paragraphe, seulement une \hbox qui sera aussi large que nécessaire, en tenant compte des autres lignes dans la même colonne).

    On pourrait implémenter ton idée avec des \makebox[2cm]{...} dans une colonne de type 'l', 'c' ou 'r', mais le package 'array' a justement un type de colonne spécial pour ça (même deux : w et W) qui évite d'avoir à taper des \makebox dans chaque cellule.

    Attention : dans tous les cas, si l'on veut vraiment 2 cm de large pour chaque colonne, il faut supprimer l'espace intercolonnes. Le tout fait encore un peu plus de 4 cm de large dans le premier exemple ci-dessous, car les trois lignes verticales contribuent à la largeur et ne sont pas affectées par le \setlength{\tabcolsep}{0pt}. Dans le deuxième exemple, j'en tiens compte et l'on peut constater que le tout, lignes comprises, fait très précisément 4 cm de large.
    \documentclass{article}
    \usepackage{xcolor}
    \usepackage{array}
    \begin{document}
    
    {%
      \setlength{\tabcolsep}{0pt}%
      \begin{tabular}{|*{2}{W{c}{2cm}|}}
      a & b\\
      \hline
      a & b\\
      \end{tabular}%
    }
    
    {\color{red!80!black}\rule{4cm}{0.4pt}}
    
    {%
      \setlength{\tabcolsep}{0pt}%
      \begin{tabular}{|*{2}{W{c}{\dimexpr 2cm -1.5\arrayrulewidth}|}}
      a & b\\
      \hline
      a & b\\
      \end{tabular}%
    }
    
    \begin{tabular}{|*{2}{W{c}{2cm}|}}
    a & b\\
    \hline
    a & b\\
    \end{tabular}
    
    \end{document}
    
    123000
    4cm.png 29.6K
  • Merci beaucoup brian ! >{\centering\arraybackslash} fonctionne parfaitement.

    Merci aussi rémi.
Connectez-vous ou Inscrivez-vous pour répondre.