[Tex/LaTex] \parbox “textwidth” for the combined width of a subset of table cells

boxestableswidth

I would like the parbox width of the text in a multicolumn to be calculated automatically from the combined width of the cells that the multicolumn spans. (Their width will vary in different copies of the table.) Is there a way of doing this?

The details are as follows: One row of my five-column table contains a multicolumn, spanning four of the columns. I want the text in that multicolumn to wrap correctly, but I don't want to specify an actual numerical width. Instead, I want the width to be determined by the actual combined width of columns 2-5 in the previous row. I've written the basic code for the table (simplified for this illustration) this way, using a tentative numerical width of "2in":

\begin{tabular}{c|c|c|c|c|} \cline{2-5}
{\bf A} & first & second & third & fourth, of variable length \\ \cline{2-5}
& \multicolumn{4}{|c|}{\parbox{2in}{fifth, also of highly variable length but
   long enough to need to wrap.}} \\ \cline{2-5}
\end{tabular}

I have used a parbox because the contents of the multicolumn contains images and text that I want to be able to treat as a unit, but I've left those details out here in order to keep the picture simple. The result looks as I want it to, except that the content of the multicolumn has too much space to the left and right, because I used an ill-chosen manual setting for the width.

The point: How can I avoid setting the parbox width manually and instead have it calculated based on the width of the other columns?

[This question was earlier posted on stackoverflow but I was urged to ask it again on this site. Thanks for your patience.]


(EDIT) Martin Scharrer's code, below produces an interesting problem for me: \colwidth seems to become only as big as the first measured column. I find that this only happens when I use certain packages that I need for Chinese in XeLaTeX:

\usepackage{xeCJK}
\usepackage{fontspec,xltxtra,xunicode}

The output becomes:

columns not working

Best Answer

You measure the width of the columns by catching them into a box using the lrbox environment and then measuring and accumulating their width (and the column separation between).

Using special column types defined with the help of the array package makes this actually very easy to handle in the tabular.

\documentclass{article}

\usepackage{array}
\newlength{\mycolwidth}
% First column (re-)sets to width.
\newcolumntype{F}{>{\global\mycolwidth=-\tabcolsep\addmycolwidth}c<{\endaddmycolwidth}}
% All other to be measured cells have type `C` which uses `c` internally:
\newcolumntype{C}{>{\addmycolwidth}c<{\endaddmycolwidth}}
% The `P` type then uses the saved width:
\newcolumntype{P}{p{\mycolwidth}}

\newsavebox{\mycolwidthbox}% box to save cells in
\newenvironment{addmycolwidth}{%
   \begin{lrbox}{\mycolwidthbox}%% catch cell content into a box
}{%
   \end{lrbox}%
   \usebox{\mycolwidthbox}%% place cell content back
   % Add width and column sep: (globally because this code is still executed inside the cell which acts like a group)
   \global\advance\mycolwidth by \wd\mycolwidthbox
   \global\advance\mycolwidth by \tabcolsep
}

\begin{document}
\begin{tabular}{c|F|C|C|C|} \cline{2-5}
\textbf{A} & first & second & third & fourth, of variable length \\ \cline{2-5}
& \multicolumn{4}{P|}{fifth, also of highly variable length but
   long enough to need to wrap.} \\ \cline{2-5}
\end{tabular}

\begin{tabular}{c|F|C|C|C|} \cline{2-5}
\textbf{B} & first & second & third & fourth, of much much longer length \\ \cline{2-5}
&  \multicolumn{4}{P|}{fifth, also of highly variable length but
   long enough to need to wrap.} \\ \cline{2-5}
\end{tabular}
\end{document}

Result:

Resulting tables

Related Question