↑↑ Home ↑ TeX tricks

Tables in TeX

The TeX macro for horizontal alignment (ie, tables) is less easy to use than the LaTeX tabular environment, but it is correspondingly more powerful. It can also save you a lot of work because things that have to be put into every cell of a given table column (eg font settings or mathematical mode) need to be specified only once. The actual table cells contain only what is different.

The TeX command for horizontal alignment is \halign. It must be followed by a group of commands enclosed by braces. This block contains all rows of the table with the cells separated by the character "&" and the rows separated by \cr. The rows containing the text actually to be printed are preceded by a special one called the preamble. It is a template into which the content of the table cells are put before being typeset. "#" characters serve as placeholders for the cell entries. (Inside macro definitions, "##" is used to avoid confusion with the macro arguments denoted by #1, #2 etc.) One # must occur between every two &s.

Here is an example for a simple table:

\halign{\hfil \it # & # \hfil \cr
3 cl & cream \cr
2 cl & beer \cr
1.5 cl & orang-utan soup \cr}
The text in the first column is printed in italics (\it) and aligned right. This is achieved by the \hfil, which is a spacer with zero default width but infinite stretchability. Whenever something is aligned right, left or centred, this is achieved with such fillers. (They come in three powers: \hfil, \hfill, and \hfilll. Each is infinitely more stretchable than its predecessor. The last one is not predefined in LaTeX, but can be emulated by writing "\hskip 0pt plus 1filll".) Likewise, the second column is aligned left.

Now for something more sophisticated. One can ignore the column template for a cell of the table, for example setting the headline cells in a different font from the other rows. This is achieved by putting an \omit before a table entry. Note that this means you also have to type the \hfils which make the alignment yourself. Everything that is part of the template is omitted.

In most cases, one wants to have frames around the table cells. This is more complicated than in LaTeX, but one also has much more choice. Here is an example:

{
\offinterlineskip
\tabskip=0pt
\halign{ 
\vrule height2.75ex depth1.25ex width 0.6pt #\tabskip=1em &
\hfil 0.#\hfil &\vrule # & \qquad$0.#\,\pi$\hfil &\vrule # &
\hfil 0.#\hfil &#\vrule width 0.6pt \tabskip=0pt\cr
\noalign{\hrule height 0.6pt}
& \omit$\alpha_s$ &&\omit star angle && \omit diquark size [fm] & \cr
\noalign{\hrule}
& 3 && 22 && 34 &\cr
& 4 && 14 && 22 &\cr
& 5 && 095 && 15 &\cr
\noalign{\hrule height 0.6pt}
}}
It has the following result when compiled:
Let's now go through the TeX code line by line. The first command switches off the spacing between lines. Normally TeX automatically inserts line spacing before starting a new line, even in tables. When typesetting framed tables, one has to disable this because otherwise the vertical lines of the frame don't join up. To make this change apply only to the table, everything is included in braces.

The second command sets the spacing between table cells to zero. This is necessary for the first column because the vertical lines have columns of their own. Without the "\tabskip=0pt", a space would be put before the vertical lines, and as a result the horizontal ones would stick out to the left of the table. (One could of course put vertical lines within the table cells containing the text, but usually it is done this way.)

Next comes the \halign command. The first item in the first cell template is a vertical ruler of the width 0.6 point. Its height (above the base line) and depth (under the base line) is given explicitly to force the table cells to be higher than they would normally be. One can also use this trick in tables without frames by setting the ruler width to zero point. Each template also has to contain a "#", even when the column is meant to remain empty as here. The last command in this template sets the column spacing back to something greater than zero.

The next column contains the first text entry. It is a numerical entry containing numbers which are smaller than 1. They are centred (since there are \hfil commands to both sides), and the zero and the decimal point are already written into the template to save me some work in the entries. Then comes another vertical rule. Its height does not have to be specified again; it will be as high as the table row. The width is the default width of 0.4 point, somewhat narrower than the outer frame. The next column contains multiples of pi. Therefore the template already contains the symbol \pi besides the zero and decimal point, in math mode. It is aligned left (\hfil on the right) but has a large space to the left (\qquad) so that the decimal points are approximately in the middle of the column. Next comes another vertical line, then the third column (centred again), and the final thick vertical line. In the template for the last column \tabskip is again set to zero to avoid horizontal lines overlapping to the right. The first \cr marks the end of the preamble.

The next command, \noalign, is often useful in tables. It allows one to insert commands between table lined which would normally only be permitted in "vertical mode", ie between paragraphs. One of these commands is a horizontal line (ruler). It extends over the whole width of the table and has the height 0.6 point. One can use \noalign for other things, too, for example inserting spaces between table lines or allowing or disabling page breaks between them (see here for an example).

Now comes the first table row. It starts with an alignment tab character (&) since the first column contains just the vertical line, no text. Likewise, later there are double &s between text entries, and the line is concluded with a &. All text entries \omit their templates since they don't contain zeros. Here no alignment is forced. In this case this results in left alignment but the result is very sensitive to spaces in the table entries. It is usually better to insert a few \hfils. After the \cr indicating the end of the table row there is another horizontal line (of default width), followed by three rows with numerical entries which are not separated by horizontal lines. After the last row there is a thick line which completes the frame. The following two braces close the \halign command and the enclosing group.

With the features described so far, one can typeset most tables in TeX. There's one more useful command: \span. It disables the alignment of the following alignment character (&) and thereby makes it possible to extend table cells over several columns. The templates of all columns are used unless one writes "\omit\span\omit\span\omit..."; otherwise just the restriction that the ampersand in this row line up with the others is removed. An example for this is the following table which at first sight seems to contain only one column:

Here the alignment mechanism was used to make the decimal points line up by putting the digits before and after the point into different columns. The source code is:
{
\offinterlineskip
\tabskip=0pt
\halign{\vrule height2.75ex depth1.25ex #\tabskip=1em &
   \qquad\hfil#\tabskip=0pt &# \hfil\tabskip=1em  &#\vrule\tabskip=0pt\cr
\noalign{\hrule}
& \omit\hfil$A$ [fm$^{1/4}$ GeV$^{7/4}$]\span  &\cr
\noalign{\hrule}
& 109.&589  &\cr
& 104.&411  &\cr
&  88.&321  &\cr
&  74.&7105 &\cr
&  88.&5942 &\cr
\noalign{\hrule}
}}
The decimal points were aligned by putting an ampersand after each of them. In order not to introduce a space after the point, \tabskip was set to zero before the corresponding alignment character (&). The title line is also interesting. The template of the first (text) column is omitted. This was done mostly to omit the spacer "\qquad"; the \hfil is added again explicitly. The \span disables the alignment but keeps the template of the following column; hence there is an implicit \hfil after the title cell which makes its text centred. (The "\tabskip=1em" is also kept but has no effect because the previous assignment was omitted.)

To make one's life easier, one can define macros containing the control sequences which have to be used every time. The first of the following macros creates a \halign table which is centred horizontally, which requires enclosing the table in a vertical box (\vbox). The others define lines (rules) making up the frame and the separators of the table. If you use them in every table, you can tinker with the appearance of all tables in a document by modifying their definitions.

\def\centretable#1{ \hbox to \hsize {\hfill\vbox{
                    \offinterlineskip \tabskip=0pt \halign{#1} }\hfill} }
\def\tabvframe{\vrule width 0.6pt height 2.75ex depth 1.25ex}
\def\tabhframe{\noalign{\hrule height 0.6pt}}
\def\tabvrule{\vrule width 0.3pt height 2.75ex depth 1.25ex}
\def\tabhrule{\noalign{\hrule height 0.3pt}}

Of course you can and should modify those macros to suit your preferences.


TOS / Impressum