2

tabular sets column widths to the widest element across all rows.

Is it possible to set two or more separate tabulars to consider each other's column widths and pick the largest of the them?

For example, if I break a tabular with additional paragraph text and want to continue the tabular as if it were a longtable crossing onto the next page (same column widths, possibly reiterating the headers), would this be possible?

7
  • 2
    Isn't it easier to used fixed lengths for tabulars then?
    – user31729
    Jun 8, 2016 at 16:27
  • Would the cells in both tabular be one-line only?
    – Bernard
    Jun 8, 2016 at 16:37
  • @ChristianHupfer Autosize for the win. I hate specifying widths; I'm looking for a robust solution.
    – kando
    Jun 8, 2016 at 17:26
  • @Bernard Do you mean single row tabulars or do you mean each row is always equal to 1em without increases from equations, multirow, or anything else? Either way: no. I'm looking for a robust solution which can handle anything.
    – kando
    Jun 8, 2016 at 17:28
  • 2
    I just mean: will your cells have line breaks, whether automatic or not?
    – Bernard
    Jun 8, 2016 at 17:36

2 Answers 2

2

The idea is to create a bunch of special column types such that every time this column type appears in a tabular it will always have the same width. This requires 2 runs of the document, where the widths computed in the first run are saved in the aux file.

Note: If you ever want to make the columns narrower, you will need to delete the aux file or at least comment out the \AtEndDocument.

\documentclass{article}
\usepackage{array}

\newsavebox{\tempbox}% \box0 etc. used

\makeatletter
\newcommand{\saveWidth}[1]% #1=column name (A,B,...)
{\immediate\write\@auxout{\string\initWidth{#1}{\the\csname Width#1\endcsname}}}

\newcommand{\initWidth}[2]% #1=column name (A,B,...), #2=the width
{\@ifundefined{Width#1}{}{\global\csname Width#1\endcsname=#2\relax}}
\makeatother

\newlength{\WidthA}% one for each column type
\newlength{\WidthB}
\newlength{\WidthC}

\AtEndDocument{\saveWidth{A}\saveWidth{B}\saveWidth{C}}

\newcolumntype{A}{>{\savebox{\tempbox}\bgroup}{l}<{\egroup%
  \ifdim\wd\tempbox>\WidthA \global\WidthA=\wd\tempbox\fi%
  \makebox[\WidthA][l]{\usebox\tempbox}}}

\newcolumntype{B}{>{\savebox{\tempbox}\bgroup}{c}<{\egroup%
  \ifdim\wd\tempbox>\WidthB \global\WidthB=\wd\tempbox\fi%
  \makebox[\WidthB][c]{\usebox\tempbox}}}

\newcolumntype{C}{>{\savebox{\tempbox}\bgroup}{r}<{\egroup%
  \ifdim\wd\tempbox>\WidthC \global\WidthC=\wd\tempbox\fi%
  \makebox[\WidthC][r]{\usebox\tempbox}}}

\begin{document}
\noindent\begin{tabular}{ABC}
left & center & right\\
wide left & wide center  & wide right
\end{tabular}

\medskip
Some text here.
\medskip

\noindent\begin{tabular}{ABC}
left & center & right\\
\end{tabular}

\medskip
Some text here.
\medskip

\noindent\begin{tabular}{ABC}
very wide left & very wide center & very wide right\\
\end{tabular}

\end{document}

To make it easier to create new columns, I added \newcolumnwidth{<name>}{l/c/r} (which is itself rather ugly).

\newcommand{\newcolumnwidth}[2]% #1=new column type, #2=l/c/r
{\expandafter\newlength\csname Width#1\endcsname%
 \AtEndDocument{\saveWidth{#1}}%
 \newcolumntype{#1}{>{\savebox{\tempbox}\bgroup}{#2}<{\egroup%
  \ifdim\wd\tempbox>\csname Width#1\endcsname \global\csname Width#1\endcsname=\wd\tempbox\fi%
  \makebox[\csname Width#1\endcsname][#2]{\usebox\tempbox}}}}

\newcolumnwidth{A}{l}
\newcolumnwidth{B}{c}
\newcolumnwidth{C}{r}
1

The approach I would follow is similar to what is done inside the tabbing environment. You set a first row that defines the tab stops and then \kill that row so it doesn't show. Subsequent rows will use these tab stops without the first row being present.

enter image description here

\documentclass{article}

\begin{document}

\noindent
\begin{tabular}{l c r}
  left      & center      &      right \\
  wide left & wide center & wide right
\end{tabular}

\medskip

Some text here.

\medskip

\noindent
\begin{tabular}{l c r}
  \phantom{wide left} &
    \phantom{wide center} & 
    \phantom{wide right} \\[-\normalbaselineskip]% Similar to \kill
  left      & center      &      right
\end{tabular}

\end{document}

The "\kill row" in the above example places the widest elements across both of your tables inside a \phantom, while the height of the row is removed using a newline of the form \\[-\normalbaselineskip].

If the content to be hidden is very tall, use \hphantom. If you're concerned about overprinting of vertical rules, don't use them (as suggested by the awesome booktabs) or insert each column element in the "\kill row" using \multicolumn{1}{l}{...} without vertical rules.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .