Know the cell width with tabular* or include a paragraph box without specifying its width

I wrote the following table using tabular* inside a \newenvironment. Worked fine but I prefer to have text wrapping on one column. The table uses "phantom" cells to achive what I want that is having one column which takes all available width that all other three (visible) columns leaves, i.e. three columns takes its minimum width depending on the text written into them, and the other column takes the remaining width. The total width is \linewidth, so that's why I did use tabular* instead of tabular. The MWE:

\documentclass{article}
\begin{document}
\begin{tabular*}{\linewidth {|c|l@{\extracolsep{\fill}}cc@{\extracolsep{0pt}}|r|r|}
minwidth& remaining width &&& minw & minw\\
x & x &&& x & x
\end{tabular*}
\end{document}


Now, what I want is text wrapping on the second visible column (the "big" one). Neither a parbox nor a p-like column can be used because of the dynamically-adjusted columns. I don't know how to read the column width of the second column to include a parbox with this width to allow text wrapping into lines.

It is possible to read a length in which tabular* stores the width of the current cell? or there is a way to include some paragraph box without specifying its length?

I can't use tabu because of [1]. Also may work tabularx but it requires some redefinition of the enddef when including it inside a new environment. Tabularx exhibited another issue which I don't remember now, but if what I need is not possible with tabular*, I'll try again with tabularx.

I did read [2]. Using '<' and '>' in column definition with lrbox doesn't solve my problem because the size of the box is restricted to the size of its contents, not the size of the resulting column.

Also I did try with zref-savepos to save the x-position of two columns to later take its difference and substracting \tabcolsep and \arrayrulewidth:

\documentclass{article}
\usepackage{zref-savepos}
\newlength{\auxleng}
\newsavebox{\auxbox}
\newenvironment{auxenviron}
{\begin{lrbox}{\auxbox}}{\end{lrbox}\usebox{\auxbox}\global\setlength{\auxleng}{\wd\auxbox}}
\begin{document}
\begin{tabular*}{\linewidth}{|c|l@{\extracolsep{\fill}}cc@{\extracolsep{0pt}}|r|r|}
minw & \zsaveposx{XX}remaining width &&& \zsaveposx{XXX} minw & minw\\
x & \setlength{\auxleng}{\zposx{XXX} sp}\addtolength{\auxleng}{-\zposx{XX} sp}\parbox{\auxleng}{asdf}&&& x & x
\end{tabular*}
\end{document}


...but every time the document is compiled, the second reference moves to the right because tabular* recalculates the position of the 2th column.

• Does package tabularx help? – Heiko Oberdiek Apr 13 '13 at 19:45
• Like tabu, can't be included directly into a \newenvironment, but unlike tabu, this can be fixed redefining the end definition of tabularx as stated in the manual of tabularx. This environment caused me a different issue but I don't remember now what it was. If what I want with tabular* is not possible, I'll try again with tabularx! – Emilio Lazo Apr 13 '13 at 19:58

Package tabularx can help. Since you are using \newenvironment, you cannot use \begin{tabularx} and \end{tabularx}, because then \end{tabularx} is hidden. However, \tabularx and \endtabularx works:

\documentclass{article}
\usepackage{tabularx}

\newenvironment{mytab}{%
\tabularx
}{%
\endtabularx
}

\begin{document}
\noindent
\begin{mytab}{\linewidth}{|c|X|r|}
minwidth& remaining width minw & minw\\
x & x & x\\
\end{mytab}
\end{document}


It is also possible to catch the contents of the environment via package environ (some restrictions for \verb stuff). Perhaps you can add your mysterious stuff at the end of the table more easily.

\documentclass{article}
\usepackage{tabularx}
\usepackage{environ}

\NewEnviron{mytab}{%
\expandafter\mytabaction\expandafter{\BODY}%
}
\newcommand{\mytabaction}[1]{%
\begin{tabularx}#1\end{tabularx}%
}

\begin{document}
\noindent
\begin{mytab}{\linewidth}{|c|X|r|}
minwidth& remaining width minw & minw\\
x & x & x\\
\end{mytab}
\end{document}

• But the class I'm writing must add some information before the end of tabularx, and this is not supported with tabularx unless you redefine the end clause of the tabularx (as mentioned in its manual). I tried this and worked giving me another problem. I'll try again with tabularx because all comments here points there. – Emilio Lazo Apr 13 '13 at 20:30
• @EmilioLazo you could put the extra code after the #1 in the \mytabaction definition (or do the same with tabularywhich uses an identical mechanism) using NewEnviron simplifies things compared to redefining TX internals, but (as Heiko knows:) there is a price that the body is scanned twice once by environ and again by tx, but that probably isn't really noticeable on modern machines as a table can't be that big. – David Carlisle Apr 13 '13 at 22:34
• Worked PERFECTLY :) I'm doing an invoice class, and the "postamble" stuff is the totalization of all items. Now with tabularx this total is three times its value, as expected. I can fix it easily, and this 3-time scanning gave me a collateral gain!! One question: Third and fourth column may be bottom-aligned when the second one has two or more lines? – Emilio Lazo Apr 14 '13 at 22:57

As tabularx already been suggested I'll give a tabulary answer. Also note that if you specify the table is full width (by any of these methods) you need to make sure that it is not indented by the paragraph indentation otherwise your line will be over-full. So you need to prefix the table by \noindent or, as here set \parindent to zero.

Also note that if you are using tabular* there is no need for the extra columns, you can switch the extra column sep for the existing columns the only slightly tricky bit is to re-insert the vertical rule.

\documentclass{article}
\usepackage{tabulary}

\makeatletter
\def\foo#1\def\TY@ratio#2#3!!{
\def\TY@checkmin{#1%
\@tempdima\TY@ratio\TY@tablewidth
\ifdim\@tempdima>\dimexpr\TY@linewidth+\hfuzz\relax
\Gscale@div\@tempb\@tempdima\TY@tablewidth
\@tempdimb\TY@ratio\p@
\edef\TY@ratio{\strip@pt\@tempdimb}%
\fi
#3}}
\expandafter\foo\TY@checkmin!!
\makeatother

\begin{document}
\parindent0pt

\begin{tabular*}{\linewidth}
{|c|l@{\extracolsep{\fill}}cc@{\extracolsep{0pt}}|r|r|}
minwidth& remaining width &&& minw & minw\\
x & x &&& x & x
\end{tabular*}

\bigskip

\begin{tabular*}{\linewidth}
{|c|l!{\extracolsep{\fill}}>{\vline\kern\tabcolsep\hfill}r!{\extracolsep{0pt}}|r|}
minwidth& remaining width & minw & minw\\
x & x & x & x
\end{tabular*}

\bigskip

\begin{tabulary}
{\linewidth}{|c|L|r|r|}
minwidth& remaining width & minw & minw\\
x & x & x & x
\end{tabulary}

\end{document}

\documentclass{article}
\usepackage{tabularx}
\begin{document}
\noindent\rule{\linewidth}{1pt}

\bigskip\noindent
\begin{tabularx}{\linewidth} {|c|Xcc|r|r|}\hline
minwidth& remaining width &&& minw & minw\\
x & x &&& x & x
\end{tabularx}
\end{document}


• The issue with tabularx is when included inside a new environment, which is what I need because I'm writing a class. Also some other issue I experienced with tabularx. What I'm asking is definitely not possible with tabular*? Using tabularx or tabu would be better than tabular* because the "phantom" columns are not needed anymore because of the X-columns. – Emilio Lazo Apr 13 '13 at 20:15
• in such a case use \tabularx ... \endtabularx instead. – user2478 Apr 13 '13 at 20:19