Thomas Fischer's Weblog

Life, Linux, LaTeX

Mehrzeilige Tabellen in LaTeX schöner machen

leave a comment »

Tabellen in LaTeX sind ein mächtiges Werkzeug zur Darstellung von Informationen. Die Darstellungsqualität von Standardtabellen kann mit ein paar kleinen Tricks aber noch verbessert werden.

Nehmen wir mal ein kleines Beispiel, wie man eine Tabelle mit bekannten SciFi-Autoren und –Büchern in LaTeX setzen würde:

Click to enlarge

\begin{tabular}{|l|l|l|}
\hline
Author & Title & Year \\
\hline
\hline
Philip K. Dick & Minority Report & 1956 \\
\hline
Philip K. Dick & Do Androids Dream of Electric Sheep? & 1968 \\
\hline
Philip K. Dick & A Scanner Darkly & 1977 \\
\hline
Neal Stephenson & Snow Crash & 1992 \\
\hline
Neal Stephenson & The Diamond Age & 1995 \\
\hline
Neal Stephenson & Cryptonomicon & 1999 \\
\hline
\end{tabular}

Die Tabelle enthält Einträge doppelt, was die Übersichtlichkeit erschwert. Um vertikal oder horizontal benachbarte Zellen zusammenzufassen, gibt es die Pakete multirow und multicol (üblicherweise bei einer TeX-Distribution enthalten).

Bei der obigen Tabelle kann man die Zellen mit gleichen Autor zu einer Zelle zusammenfassen:

Click to enlarge

\begin{tabular}{|l|l|l|}
\hline
Author & Title & Year \\
\hline
\hline
\multirow{3}{*}{Philip K. Dick} & Minority Report & 1956 \\
\hline
 & Do Androids Dream of Electric Sheep? & 1968 \\
\hline
 & A Scanner Darkly & 1977 \\
\hline
\multirow{3}{*}{Neal Stephenson} & Snow Crash & 1992 \\
\hline
 & The Diamond Age & 1995 \\
\hline
 & Cryptonomicon & 1999 \\
\hline
\end{tabular}

Ein ähnliches Ergebnis hätten wir erreichen können, wenn wir die Autorennamen in die Zelle links vom jeweils 2. Buch eingetragen hätten. Sowas funktioniert aber nur mit einer ungeraden Anzahl Bücher.

Was jetzt noch stört, sind die horizontalen Linien direkt über und unter den Autorennamen. Das Problem kann man lösen, indem man \hline durch \cline{2-3} ersetzt. Dadurch wird die horizontale Linie nur durch die angegebenen Spalten gezeichnet.

Click to enlarge

\begin{tabular}{|l|l|l|}
\hline
Author & Title & Year \\
\hline
\hline
\multirow{3}{*}{Philip K. Dick} & Minority Report & 1956 \\
\cline{2-3}
 & Do Androids Dream of Electric Sheep? & 1968 \\
\cline{2-3}
 & A Scanner Darkly & 1977 \\
\hline
\multirow{3}{*}{Neal Stephenson} & Snow Crash & 1992 \\
\cline{2-3}
 & The Diamond Age & 1995 \\
\cline{2-3}
 & Cryptonomicon & 1999 \\
\hline
\end{tabular}

Ein Problem beim den Standardtabellen ist, daß der vertikale Abstand zwischen den horizontalen Linien (\hline bzw. \cline) und dem Text zu klein ist. Außerdem erscheint der Abstand stark asymmetrisch, wie diese Vergrößerung zeigt:

Die Lösung für dieses Problem stellt das booktabs-Paket bereit; hier wird der Abstand zwischen Linien und Text vergrößert. Das Paket stellt zwei Design-Paradigmen auf:

  1. Vertikale Linien sind böse
  2. Doppelte Linien sind böse

Damit Linien sauber und kontextsensitiv dargestellt werden, definiert das booktabs-Paket neue Linientypen für den Kopf und Fuss einer Tabelle sowie Linien dazwischen. Die Pipe-Symbole aus der Tabellen-Deklaration müssen entfernt werden, weil die vertikalen Linie zu Darstellungsfehlern in Kombination mit den booktabs-Linien führen.

Click to enlarge

\begin{tabular}{lll}
\toprule
Author & Title & Year \\
\midrule
\multirow{3}{*}{Philip K. Dick} & Minority Report & 1956 \\
\cmidrule{2-3}
 & Do Androids Dream of Electric Sheep? & 1968 \\
\cmidrule{2-3}
 & A Scanner Darkly & 1977 \\
\midrule
\multirow{3}{*}{Neal Stephenson} & Snow Crash & 1992 \\
\cmidrule{2-3}
 & The Diamond Age & 1995 \\
\cmidrule{2-3}
 & Cryptonomicon & 1999 \\
\bottomrule
\end{tabular}

Die Tabelle ist jetzt etwa um ein Drittel höher geworden. Außerdem scheinen die Autorenamen etwas nach oben verrutscht zu sein. Das kommt daher, daß das multirow-Paket nicht merkt, daß die Linien des booktabs-Pakets vertikale Abstände eingefügt haben und somit die Höhe der Zeilen falsch bestimmt wird.

Es gibt zwei Möglichkeiten, das Aussehen zu korrigieren: Entweder werden die \cmidrule-Linien entfernt (und damit auch die Extra-Abstände) oder der \multirow-Befehl muss „überlistet“ werden.

Erstmal die Variante ohne Linien:

Click to enlarge

\begin{tabular}{lll}
\toprule
Author & Title & Year \\
\midrule
\multirow{3}{*}{Philip K. Dick} & Minority Report & 1956 \\
 & Do Androids Dream of Electric Sheep? & 1968 \\
 & A Scanner Darkly & 1977 \\
\midrule
\multirow{3}{*}{Neal Stephenson} & Snow Crash & 1992 \\
 & The Diamond Age & 1995 \\
 & Cryptonomicon & 1999 \\
\bottomrule
\end{tabular}

Für die zweite Variante definiere ich einen alternativen multirow-Befehl. Die Idee dahinter ist, mit \vspace* gerade den Abstand (\aboverulesep und \belowrulesep pro Linie) wieder abzuziehen, der durch die \midrule– bzw. \cmidrule-Aufrufe eingefügt werden.

Der neue Befehl \multirowbt nimmt an, daß bei mehrzeiligen Zellen zwischen jeder Zeile ein \cmidrule-Aufruf ist. Falls das nicht der Fall ist, muß man sich mit dem alten \multirow und \compensaterule mit entsprechendem Parameter behelfen.

In der Dokument-Präamble werden daher die folgenden Befehle definiert:

\newcommand{\forloop}[5][1]{%
\setcounter{#2}{#3}%
\ifthenelse{#4}{#5\addtocounter{#2}{#1}%
\forloop[#1]{#2}{\value{#2}}{#4}{#5}}%
{}}
\newcounter{crcounter}
\newcommand{\compensaterule}[1]{%
\forloop{crcounter}{1}{\value{crcounter} < #1}%
{\vspace*{-\aboverulesep}\vspace*{-\belowrulesep}}}
\newcommand{\multirowbt}[3]{\multirow{#1}{#2}%
{\compensaterule{#1}#3}}

Die \forloop-Konstruktion habe ich auf CTAN gefunden Damit das ganze funktioniert, muß das Paket ifthen eingebunden werden.

Die endgültige Tabelle sieht dann so aus:

Click to enlarge

\begin{tabular}{lll}
\toprule
Author & Title & Year \\
\midrule
\multirowbt{3}{*}{Philip K. Dick} & Minority Report & 1956 \\
\cmidrule{2-3}
 & Do Androids Dream of Electric Sheep? & 1968 \\
\cmidrule{2-3}
 & A Scanner Darkly & 1977 \\
\midrule
\multirowbt{3}{*}{Neal Stephenson} & Snow Crash & 1992 \\
\cmidrule{2-3}
 & The Diamond Age & 1995 \\
\cmidrule{2-3}
 & Cryptonomicon & 1999 \\
\bottomrule
\end{tabular}

Dem Leser wird als Übung überlassen, dem Befehl \multirowbt einen optionalen Parameter einzubauen, mit dem man die Anzahl der überbrückten Linien übergeben kann.

Advertisements

Written by Thomas Fischer

April 11, 2007 at 0:00

Posted in LaTeX

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: