Writing a table with equally spaced columns, based on the widest column

Well, I've been solving this problem before and I ended with quite a universal solution, see the example (you need to run the code twice to get the correct result):

enter image description here

\documentclass{article}

\usepackage{array}

\makeatletter
\newlength\eqcol@newlen
\newlength\eqcol@oldlen
\let\eqcol@bc\hfil
\let\eqcol@ec\hfil
\let\eqcol@br\hfil
\let\eqcol@el\hfil
\newcolumntype{e}[1]{%
  >{\setbox0\hbox\bgroup}#1%
  <{\egroup
    \ifdim\wd0<\eqcol@newlen\else\global\eqcol@newlen\wd0\fi
    \ifdim\wd0<\eqcol@oldlen\else\global\eqcol@oldlen\wd0\fi
    \hbox to \eqcol@oldlen{%
      \csname eqcol@b#1\endcsname
      \box0 %
      \csname eqcol@e#1\endcsname
    }%
  }%
}
\newcount\eqcol@count
\def\eqcolRead{%
  \global\advance\eqcol@count1 %
  \eqcol@oldlen5em\relax
  \csname eqcol@def@\romannumeral\eqcol@count\endcsname
}
\def\eqcolWrite{%
  \immediate\write\@auxout{%
  \gdef\expandafter\noexpand\csname eqcol@def@\romannumeral\eqcol@count\endcsname
    {\global\eqcol@oldlen\the\eqcol@newlen\relax}%
  }%
  \global\eqcol@newlen0pt\relax
}
\let\eqcol@old@tabular\tabular
\def\tabular{\eqcolRead\eqcol@old@tabular}
\let\eqcol@old@endtabular\endtabular
\def\endtabular{\eqcol@old@endtabular\eqcolWrite}
\makeatother

\begin{document}

\begin{tabular}{|el|er|}
\hline
111 & 22 \\\hline
33 & 4444444 \\\hline
\end{tabular}

\begin{tabular}{|ec|er|}
\hline
1 & 22 \\\hline
3 & 4 \\\hline
\end{tabular}

\begin{tabular}{|el|er|}
\hline
111 & 22 \\\hline
33 & 444444 \\\hline
\end{tabular}

\[
A =
  \eqcolRead\begin{array}{*3{ec}}
  1 & 10000 & 1 \\ 1 & 1 & 1
  \end{array}\eqcolWrite
\]

\end{document}

The tabular environment is tweaked by default, in other cases, you have to do it manually (see the array example above).


This is inspired by tohecz, but uses a dedicated environment, which I believe is better.

In a equalizedtabular one can use any column specifier, not just L, C or R, but of course only these will be equalized. Two passes are necessary, since the .aux file is used, and upon inclusion of an equalizedtabular between two of them the first compilation will give wrong results; however, the next run of LaTeX will fix the lengths.

\documentclass{article}

\usepackage{array,collcell}

\newcolumntype{C}{>{\collectcell\docellC}c<{\endcollectcell}}
\newcolumntype{L}{>{\collectcell\docellL}c<{\endcollectcell}}
\newcolumntype{R}{>{\collectcell\docellR}c<{\endcollectcell}}

\makeatletter
\providecommand{\@nameedef}[1]{\expandafter\edef\csname#1\endcsname}
\newcommand{\docell}[2]{%
  \sbox\equalizedtablebox{#2}%
  \ifdim\wd\equalizedtablebox>\@nameuse{finallen\theequalizedtable}\relax
    \global\@nameedef{finallen\theequalizedtable}{\the\wd\equalizedtablebox}%
  \fi
  \makebox[\@nameuse{startinglen\theequalizedtable}][#1]{#2}%
}
\newcommand{\docellC}[1]{\docell{c}{#1}}
\newcommand{\docellL}[1]{\docell{l}{#1}}
\newcommand{\docellR}[1]{\docell{r}{#1}}
\newcounter{equalizedtable}
\newsavebox\equalizedtablebox
\newenvironment{equalizedtabular}[2][c]
  {%
   \stepcounter{equalizedtable}%
   \global\@namedef{finallen\theequalizedtable}{0pt}%
   \@ifundefined{startinglen\theequalizedtable}
    {\@namedef{startinglen\theequalizedtable}{5em}}{}
   \tabular[#1]{#2}%
  }
  {%
   \endtabular
   \begingroup\edef\x{\endgroup
     \write\@auxout{%
       \global\noexpand\noexpand\noexpand\@namedef{startinglen\theequalizedtable}%
     {\@nameuse{finallen\theequalizedtable}}%
   }}\x
  }
\makeatother
\begin{document}

\begin{equalizedtabular}{|L|C|}
\hline
111 & 22 \\\hline
33 & 4444444 \\\hline
\end{equalizedtabular}

\begin{equalizedtabular}{|R|C|}
\hline
111 & 22 \\\hline
33 & 4 \\\hline
\end{equalizedtabular}

\end{document}

enter image description here


I'd change the input syntax a bit:

enter image description here

\documentclass{article}

\makeatletter
\def\paulo#1{\count@#1\relax\leavevmode\setbox\z@\vbox\bgroup}
\def\endpaulo{\egroup\dimen@\wd\z@\global\setbox\@ne\null
\setbox\z@\vbox{\unvbox\z@\loop\unskip\unskip\setbox\z@\lastbox
\ifvoid\z@\else
\global\setbox\@ne\hbox{\hbox to\dimen@{\box\z@\hfil}\penalty\z@\unhbox\@ne}%
\repeat}%
\vbox{\hsize\count@\dimen@\noindent\unhbox\@ne}}

\def\cell#1{\hbox{\kern\tabcolsep\ignorespaces#1\unskip\kern\tabcolsep}}

\makeatother
\begin{document}

\begin{paulo}{2}
\cell{a}
\cell{b}
\cell{c}
\cell{Mary had a little lamb}
\end{paulo}

\end{document}