2

I like to use a table layout where the width of the table is fixed to 7cm. I can do this using:

\documentclass{book}
\usepackage{array,tabularx}
\newcolumntype{+}{>{\global\let\currentrowstyle\relax}}
\newcolumntype{^}{>{\currentrowstyle}}
\newcommand{\rowstyle}[1]{\gdef\currentrowstyle{#1}%
  #1\ignorespaces}

\makeatletter
\g@addto@macro\@floatboxreset{\centering\sffamily\small}
\makeatother


\begin{document}

\begin{table}

\begin{tabular*}{7cm}{@{\extracolsep{\fill}}|>{\bfseries}+l|^c|^c|}
\hline\rowstyle{\bfseries}%
            & property  & number    \\ \hline
Something   & yes       & 1554      \\
Item        & no        & 2         \\ \hline
\end{tabular*}\\
\vspace{.5cm}

\newcolumntype{;}{l@{}}% dummy column
\begin{tabular*}{7cm}{@{\extracolsep{\fill}}|;>{\bfseries}+l;|^c;|^c;|}
\hline\rowstyle{\bfseries}%
&            && property  && number  &  \\ \hline
&Something   && yes       && 1554    &  \\
&Item        && no        && 2       &  \\ \hline
\end{tabular*}\\
\vspace{.5cm}

\newcolumntype{;}{X@{}}% dummy column
\begin{tabularx}{7cm}{|+;>{\bfseries}l;|;^c;|;^c;|}
\hline\rowstyle{\bfseries}%
&            &&& property  &&& number   & \\ \hline
&Something   &&& yes       &&& 1554     & \\
&Item        &&& no        &&& 2        & \\ \hline
\end{tabularx}\\
\vspace{.5cm}

\setlength{\tabcolsep}{.52cm}
\begin{tabular}{|>{\bfseries}+l|^c|^c|}
\hline\rowstyle{\bfseries}%
            & property  & number    \\ \hline
Something   & yes       & 1554      \\
Item        & no        & 2         \\ \hline
\end{tabular}


\end{table}

\end{document} 

In the code, the first table doesn't align nicely. The second and third table require the use complex code for formatting the table in the document. Where I'd rather separate the formatting from the contents. The fourth example works nicely, but requires manual tuning of tabcolsep.

How should I define a tabular environment that dynamically increases the cell margins to obtain the desired table width?

5
  • 2
    Use the tabularx package, see texdoc tabularx.
    – Christoph
    Commented Sep 20, 2013 at 11:14
  • @Christoph: Then you would have to know the width of column without space to calculate the right factors for the X columns to get evenly distributed space across columns. Commented Sep 20, 2013 at 11:26
  • You could look at tabularx or tabulary packages, but the space added by \extracolsep is evenly distributed if you add a final @{} after the | to match the @{} at the start. (or use ! instead of @ so it does not remove the \tabcolsep at that point. Commented Sep 20, 2013 at 11:28
  • It always helps if you post a small complete example document that shows the problem. Commented Sep 20, 2013 at 11:29
  • @DavidCarlisle, I could not get your suggestions to work. The '!' version does compile, but the only change is small lines sticking out at the left. Adding '@{}' also does not improve the situation. I did add a full example document now.
    – GrowMyHair
    Commented Sep 20, 2013 at 11:52

2 Answers 2

4

Usually LaTeX does not use TeX's \tabskip to set the space between the columns, but it uses the dimen register \tabcolsep. The latter is also inserted between a column and the vertical line opposite to \tabskip that is only inserted between columns. \extracolsep sets \tabcolsep. The example in the question contains a table with three columns, six \tabcolsep and two \tabskip.

Therefore a workaround is the use of dummy columns:

\documentclass[a5paper]{article}

\usepackage{array}
\newcolumntype{;}{l@{}}% dummy column

\begin{document}

\noindent
\begin{tabular*}{\linewidth}{@{\extracolsep{\fill}}|;l;|c;|c;|}
\hline
&     && 1   && 2  &\\ \hline
& a   && x   && 15 &\\
& b   && y   && 2  &\\ \hline
\end{tabular*}

\end{document}

Result tabular*

Variant with \rowstyle:

\documentclass[a5paper]{article}

\usepackage{array}
\newcolumntype{;}{l@{}}% dummy column

\newcolumntype{+}{>{\global\let\currentrowstyle\relax}}
\newcolumntype{^}{>{\currentrowstyle}}
\newcommand*{\rowstyle}[1]{%
  \gdef\currentrowstyle{#1}%
  #1\ignorespaces
}

\begin{document}

\noindent
\begin{tabular*}{\linewidth}{@{\extracolsep{\fill}}|+;>{\bfseries}l;|^c;|^c;|}
\hline
\rowstyle{\bfseries}%
&     && 1   && 2  &\\ \hline
& a   && x   && 15 &\\
& b   && y   && 2  &\\ \hline
\end{tabular*}

\end{document}

Result tabular* with \rowstyle

Another workaround is tabularx with dummy X columns. These columns are the place where the evenly distributed space should go:

\documentclass[a5paper]{article}

\usepackage{tabularx}
\usepackage{array}
\newcolumntype{;}{X@{}}% dummy column

\begin{document}

\noindent
\begin{tabularx}{\linewidth}{|;l;|;c;|;c;|}
\hline
&     &&& 1   &&& 2  &\\ \hline
& a   &&& x   &&& 15 &\\
& b   &&& y   &&& 2  &\\ \hline
\end{tabularx}

\end{document}

Result tabularx

Variant with \rowstyle:

\documentclass[a5paper]{article}

\usepackage{tabularx}
\usepackage{array}
\newcolumntype{;}{X@{}}% dummy column

\newcolumntype{+}{>{\global\let\currentrowstyle\relax}}
\newcolumntype{^}{>{\currentrowstyle}}
\newcommand*{\rowstyle}[1]{%
  \gdef\currentrowstyle{#1}%
  #1\ignorespaces
}

\begin{document}

\noindent
\begin{tabularx}{\linewidth}{|+;>{\bfseries}l;|;^c;|;^c;|}
\hline
\rowstyle{\bfseries}%
&     &&& 1   &&& 2  &\\ \hline
& a   &&& x   &&& 15 &\\
& b   &&& y   &&& 2  &\\ \hline
\end{tabularx}

\end{document}

Result tabularx with \rowstyle

2
  • Thanks for the suggestions. I tried both and adapted my example to include them. They do get me nice alignment, but the '\rowstyle' command no longer works. Moveover, they complicate the code for writing the table quite a bit.
    – GrowMyHair
    Commented Sep 20, 2013 at 12:48
  • Rowstyle indeed just works. My mistake when implementing.
    – GrowMyHair
    Commented Sep 20, 2013 at 13:14
2

The space added by \extracolsep is added evenly between the columns but the vertical rules are not placed in the centre of that space, but before it, so one option is simply don't use vertical rules. Alternatively tx or ty might come to your rescue:

See Is it possible to make an underfull tabulary spread out?

for the TY patch.

enter image description here

\documentclass{book}
\usepackage{array,tabularx,tabulary}
\newcolumntype{+}{>{\global\let\currentrowstyle\relax}}
\newcolumntype{^}{>{\currentrowstyle}}
\newcommand{\rowstyle}[1]{\gdef\currentrowstyle{#1}%
  #1\ignorespaces} 
\tymin0pt
\makeatletter


\def\foo#1\def\TY@ratio#2#3!!{
\def\TY@checkmin{#1%
 \@tempdima\TY@ratio\TY@tablewidth
 \ifdim\@tempdima>\TY@linewidth
  \advance\@tempdima-\TY@linewidth
  \Gscale@div\@tempb\@tempdima\TY@tablewidth
  \@tempdimb\TY@ratio\p@
  \advance\@tempdimb-\@tempb\p@
  \edef\TY@ratio{\strip@pt\@tempdimb}%
\fi
#3}}
\expandafter\foo\TY@checkmin!!



\makeatother

\makeatother

\makeatletter
\g@addto@macro\@floatboxreset{\centering\sffamily\small}
\makeatother

\begin{document}

\begin{table}
\begin{tabular*}{.95\textwidth}{@{\extracolsep{\fill}}|>{\bfseries}+l|^c|^c|}
\hline\rowstyle{\bfseries}%
    & 1   & 2 \\ \hline
a   & x   & 15\\
b   & y   & 2 \\ \hline
\end{tabular*}

\bigskip
\begin{tabular*}{.95\textwidth}{@{\extracolsep{\fill}}>{\bfseries}+l^c^c@{}}
\hline\rowstyle{\bfseries}%
    & 1   & 2 \\ \hline
a   & x   & 15\\
b   & y   & 2 \\ \hline
\end{tabular*}

\bigskip

\begin{tabularx}{.95\textwidth}{@{}|>{\bfseries}+l|^>{\centering\arraybackslash}X|^>{\centering\arraybackslash}X|@{}}
\hline\rowstyle{\bfseries}%
    & 1   & 2 \\ \hline
a   & x   & 15\\
b   & y   & 2 \\ \hline
\end{tabularx}

\bigskip

\begin{tabulary}{.95\textwidth}{|>{\bfseries}+L|^C|+C|}
\hline\rowstyle{\bfseries}%
    & 1   & 2 \\ \hline
a   & x   & 15\\
b   & y   & 2 \\ \hline
\end{tabulary}
\end{table}

\end{document} 

You must log in to answer this question.

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