# Calculate width of environment within the environment

In the Outer environment I want the TableWidth to be always exactly as wide as the tabular (of the Inner environment) that precedes it, so that the text in the last line of the 2nd example is on 1 line.

I have the feeling this could be done using the environ package, but I have no idea how to combine that with a \NewDocumentEnvironment.

My MWE

\documentclass{article}
\usepackage{
array,%         actions for tabular column cells
collcell,%      macro calls for tabular column cells
xparse,%        optional params and starred commands
ifthen,%        easy booleans, tests and loops
}

\newlength\TableWidth

\newcommand\Tfer[1]{%
\ifthenelse{\equal{#1}{A}}{%
\textbf{CAB}\relax%
}{%
#1\relax%
}%
}

\newcolumntype{T}{>{\collectcell\Tfer}c<{\endcollectcell}}

\newenvironment{Inner}[1][t]{%
\begin{tabular}[#1]{TTTT}%
}{\end{tabular}}

\NewDocumentEnvironment{Outer}{O{t}D(){\empty}}{%
\begin{Inner}[#1]%
}{%
\ifx#2\empty\else%
\multicolumn{4}{l}{%
\footnotesize%
\begin{tabular}{p{\TableWidth}}\hline%
#2%
\end{tabular}%
}%
\fi%
\end{Inner}%
}%

\begin{document}

\setlength\TableWidth{2.5cm}

\begin{Outer}(\raggedright some very long testing text)
1 & B & b  & bb \\
2 & A & ll & a \\
\end{Outer}

\begin{Outer}(\raggedright some very long testing text)
123456789 & BBBBB & bbb & bbbb \\
234567890 & A     & lll & aaaa \\
\end{Outer}

\end{document}

• Why do you want the tabular with the \Tablewidth inside the inner tabular? It would be much easier if you would simply add it behind. – Ulrike Fischer Aug 7 '17 at 12:58
• @Ulrike: Because my very limited knowledge of LaTeX prohibited me of thinking of another possible way of doing it. – Jack Aug 7 '17 at 14:22

You need no inner environment: the idea is to set the table proper in a box, then use an outer tabular once we know the width of the main table part.

\documentclass{article}
\usepackage{
collcell,%      macro calls for tabular column cells
xparse,%        optional params and starred commands
}

\newcolumntype{T}{>{\collectcell\Tfer}c<{\endcollectcell}}
\newsavebox{\jackbox}

\ExplSyntaxOn
\NewDocumentCommand\Tfer{m}
{
\str_if_eq:nnTF { #1 } { A } { \textbf{CAB} } { #1 }
}
\ExplSyntaxOff

\NewDocumentEnvironment{Outer}{O{t}d()}
{
\begin{lrbox}{\jackbox}
\begin{tabular}[#1]{@{}TTTT@{}}
}
{
\end{tabular}
\end{lrbox}
\begin{tabular}[#1]{p{\wd\jackbox}}
\usebox{\jackbox}
\\
\IfValueT{#2}{\hline\footnotesize #2}
\end{tabular}
}

\begin{document}

\begin{Outer}(\raggedright some very long testing text)
1 & B & b  & bb \\
2 & A & ll & a \\
\end{Outer}

\begin{Outer}(\raggedright some very long testing text)
123456789 & BBBBB & bbb & bbbb \\
234567890 & A     & lll & aaaa \\
\end{Outer}

\end{document}


• @Ulrike Your answer is (as always) sophisticated. It would have never struck my mind to use a package that "...tries to get rid of the restriction in LATEX’s reference system..." for calculating the width of an environment. – Jack Aug 8 '17 at 10:59
• I grabbed your first approach, before you removed it. I implemented it in my real problem and it seems to work well. All the same I am intrigued by your 2nd solution, but I have some questions before I can use it. See my answer for details. – Jack Aug 8 '17 at 11:01
• No reaction at all? Shouldn't I have put it as an answer? Or is the stuff too complicated (or too ridiculous)? – Jack Aug 9 '17 at 5:51
• @Jack You should have asked a new question. – egreg Aug 9 '17 at 8:48

You could store the position before and after the tabular and then calculate the difference. To avoid that the innermost tabular interfere you can set its visible length to zero. I wasn't sure what you want to do with the tabcolsep at the margins. If needed you will have to adapt it.

\documentclass{article}
\usepackage{
array,%         actions for tabular column cells
collcell,%      macro calls for tabular column cells
xparse,%        optional params and starred commands
ifthen,%        easy booleans, tests and loops
}

\usepackage[savepos]{zref}

\newlength\TableWidth
\newcounter{postmpcnt}

\newcommand\Tfer[1]{%
\ifthenelse{\equal{#1}{A}}{%
\textbf{CAB}\relax%
}{%
#1\relax%
}%
}

\newcolumntype{T}{>{\collectcell\Tfer}c<{\endcollectcell}}

\newenvironment{Inner}[1][t]
{%
\stepcounter{postmpcnt}%
\setlength\TableWidth{%
\dimexpr
\zposx{stoppos-\number\value{postmpcnt}}sp -
\zposx{startpos-\number\value{postmpcnt}}sp
\relax}%
%
\leavevmode\zsaveposx {startpos-\number\value{postmpcnt}}%
\begin{tabular}[#1]{TTTT}%
}
{\end{tabular}%
\zsaveposx {stoppos-\number\value{postmpcnt}}}

\NewDocumentEnvironment{Outer}{O{t}D(){\empty}}{%
\begin{Inner}[#1]%
}{%
\ifx#2\empty\else%
\multicolumn{1}{l}{%
\footnotesize%
\makebox[0pt][l]{\begin{tabular}{@{}p{\dimexpr\TableWidth-2\tabcolsep}@{}}\hline%
#2%
\end{tabular}}}%
%
\fi%
\end{Inner}%
}%

\begin{document}

\setlength\TableWidth{2.5cm}

\begin{Outer}(\raggedright some very long testing text)
1 & B & b  & bb \\
2 & A & ll & a \\
\end{Outer}

\begin{Outer}(\raggedright some very long testing text)
123456789 & BBBBB & bbb & bbbb \\
234567890 & A     & lll & aaaa \\
\end{Outer}

\end{document}