# Vertically aligned table in plainTeX / LaTeX / Context etc

My last answer about vertically aligned table inspired me to write my first question at this site. How to create the following table in various TeX approaches: plainTeX, LaTeX, Context, eplain, OPmac etc.? The comparison would be welcome.

The table has given column widths, each data item is vertically centered, some data items can be vertically spanned and vertically centered in its space. Data items are one of the two types: single centered line in the column or the paragraph. There are single lines between columns and between lines. The table looks like:

It would be fine to separate the code to two parts: first part will be signed as % macro code created by the macro programmer and/or typo designer. The second part is signed as % document and the author of the text is supposed to write it.

I'll give the answer for plainTeX (this is my domain). I am looking forward to another approaches.

As a bonus you can try to create the table from my book TeXbook inside out (full text is available here) from the page 142. The vertical aligning is here too: the last but one line is vertically centered and the the last line is aligned to the top.

Edit I am still waiting for LaTeX solution. One user mentioned in comments that this is worse aspect from typographical point of view. But I am not evaluating the typographical quality of many examples presented at tex.stackexchange. Why do it with this special case? For example, my customer asked me for creating the following excel-like table:

This is not used for printing in book but only as a tool printed on paper sheets to do data more transparent. This is typical example for \valign usage.

Is there a LaTeX approach to do this? LaTeX is mentioned here in 98 % of threads. Can we found somebody to explain this from LaTeX point of view? Or LaTeX isn't able to do it (without absorbing the plain TeX solution)?

Note: the vertical-alignment tag includes 1030 threads. What can be more natural than \valign primitive for such request...

Today, there is very similar question Different vertical alignment with multirow.

-
This is simply a badly laid out table, why bother? ;-) –  egreg Jun 5 '14 at 6:50
@egreg This evasion is very ferquent if something is more complicated:). Moreover this was the primary question where I was referred (by @Olumide) and there are 4 answers here with misconception the original question. You can omit the vertical lines if you feel them as bad. –  wipet Jun 5 '14 at 7:09
It's mid vertical alignment the worse aspect in the table, closely followed by the vertical rules. –  egreg Jun 5 '14 at 7:23
@egreg Why didn't you mention about worse aspect in the previous thread "centering multirow text in a table..."? Read the question from it carefully: The multirow text "spring" is NOT centered over the three rows that it spans. My interest is: is there a LaTeX and/or Context solution for this intelligent \multirow? I don't know. You can simply say: LaTeX is not able to do it. Please do detach the typographical aspect of this, this was not mine proposal. I did use \valign in many more cases in my practice and I am interesting how this is solved in another TeX macro packages. –  wipet Jun 5 '14 at 8:36
@wipet: AFAIK, with the \halign/\valign-primitives, you can only do either \multispan for columns in \halign, or for rows in \valign, but not both in the same table. –  morbusg Jun 5 '14 at 10:58

With ConTeXt:

\def\blah{blah blah blah blah }
\switchtobodyfont[10pt]
\starttext
\bTABLE
\setupTABLE[offset=1em]
\setupTABLE[column][each][align={middle, lohi}]
\setupTABLE[column][3][align=right, width=.3\textwidth]
\bTR\bTH Type\eTH         \bTH Specs\eTH   \bTH[align=middle] Uses\eTH\eTR
\bTABLEbody
\bTR\bTD\eTD              \bTD Model 1\eTD \bTD \blah\blah \eTD\eTR
\bTR\bTD[nr=3] Spring\eTD \bTD Model 2\eTD \bTD \blah\blah\blah\blah\blah\blah blah blah blah \eTD\eTR
\bTR                      \bTD Model 3\eTD \bTD \blah\blah \eTD\eTR
\bTR                      \bTD Model 4\eTD \bTD \blah\blah blah blah blah \eTD\eTR
\eTABLEbody
\eTABLE
\stoptext


which looks like

-
How ConTeXt do it? May be there are many passes throw the table data... –  wipet Jun 5 '14 at 10:30
@wipet: I don't know, but you can find the source for these "natural tables" in \$TEXMF-DIST/tex/context/base/tabl-ntb.mkiv. ConTeXt sources are usually pretty pleasant to read. –  morbusg Jun 5 '14 at 10:49
@wipet: Yes, ConTeXt uses a too pass mechanism. The first pass to determine the maximum width of each cell, and the second pass to do the actual typesetting. Similar approach is also taken by LaTeX when typesetting aligned equations (align, falign, etc.) –  Aditya Jun 5 '14 at 12:50

The plainTeX approach is here. This is my answer from here slightly improved. Two new features are here:

• The code is divided to the macro part (done by macro programator) and document part (done by author).
• The author can set the width of each column used in the table.

The code

% Macro code (by programator and designer)
\newcount\tmpnum
\expandafter \setcolumnsA \fi
}
\def\vtable #1#2{\vbox{\hbox{%
\tmpnum=180 \setcolumnsA #1,,\tmpnum=180
\valign{&\hrule\vfil\vbox{\setrowparams\topstrut##\unskip\botstrut}\vfil\crcr
#2\crcr}}\hrule}%
}
\def\multirow#1#2{\multispan{#1}\hrule\vfil\vbox{\setrowparams\topstrut#2\botstrut}\vfil}
\def\topstrut{\vbox to3ex{}} \def\botstrut{\vtop to2ex{}}
\def\setrowparams{\hsize=\dimen\tmpnum \leftskip=.5em \rightskip=\leftskip
\ifdim\hsize=0pt \hsize=100pt \message{WARNING: the columnwidth is not set.}\fi
\emergencystretch=2em \noindent\hfil}
\let\dopar=\hfilneg  % the items of paragraph format are prefixed by \dopar

% document (by author):
\def\blah{blah blah blah blah blah blah blah blah}
\def\blahh{\blah\ \blah\ \blah\  blah blah blah}

\vtable{25mm,25mm,40mm}{
Type   & & \multirow3{Spring} \cr
Specs  & Model 1 & Model 2 & Model 3 & Model 4 \cr
Uses   & \dopar\blah & \dopar\blahh & \dopar\blah & \dopar blah blah \blah\ blah \cr
}

\end


You can process it by tex document or pdftex document. The result is the same as the table given in the question.

-

I would show the solution based on OPmac. This macro package provides the \table command to create tables. Of course it uses \halign primitive. The following solution defines the \vtable alternative for \table based on \valign primitive. It redefines locally a few internal macros from OPmac. This is done in the \vtabledefs macro. A \vrule <-> \hrule, \vfil <-> \hfil etc. changes are performed here.

The user (in % document part) of the code can enjoy the OPmac table features, for example the non-intersected double lines.

% macros:
\input opmac

\def\vtable{\hbox\bgroup \catcode\|=12 \vtabledefs \tableB}
\def\tableB#1#2{\offinterlineskip \def\tmpa{}\tabdata={}\scantabdata#1\relax
\valign\expandafter{\the\tabdata\tabstrutA\cr#2\crcr}\egroup}
\def\vtabledefs{%
\let\dopar=\hfilneg  % the items of paragraph format are prefixed by \dopar
\def\setrowparams{\hsize=\dimen\tmpnum \leftskip=.5em \rightskip=\leftskip
\normalbaselines \hsize=\tmpdim
\emergencystretch=2em \noindent\hfil}%
\def\topstrut{\vbox to3ex{}}\def\botstrut{\vtop to2ex{}}%
\def\tabstrut{}%
\def\multirow##1##2{\multispan{##1}\vfil\vbox{\setrowparams\topstrut##2\botstrut}\vfil\hrule}%
\def\crl{\crcr\noalign{\vrule}}%
\def\colw=##1 {\noalign{\global\tmpdim=##1}}%
\def\crli{\crcr \omit \gdef\dditem{\omit\tablinefil}\gdef\vvitem{\tabvvline}%
\vvleft\tablinefil\ddlinedata\cr}%
\def\tabvvline{\hrule\kern\hhkern\hrule}%
\def\crlli{\crli\noalign{\kern\vvkern}\crli}%
\tmpdim=100pt
\def\tabdeclarec{\medskip\vfil\vbox{\setrowparams\topstrut####\unskip\botstrut}\vfil\medskip}%
}
\def\vvkern{2pt} \def\hhkern{2pt}

% document:

\def\blah{blah blah blah blah blah blah blah blah}
\def\blahh{\blah\ \blah\ \blah\  blah blah blah}

\frame{\vtable{|c||c||c|c|c|}{\crli
\colw=20mm Type  & & \multirow3{Spring} \crlli
\colw=20mm Specs & Model 1 & Model 2 & Model 3 & Model 4 \crlli
\colw=40mm Uses  & \dopar\blah & \dopar\blahh & \dopar\blah & \dopar\blah\ blah \crli
}}
\bye


OPmac provides colors too. Then the second example uses this feature. The \vtabledefs is similar as above but new macros for colorization backgrounds of the items are added. Use pdftex to process it.

% macros:
\input opmac

\def\vtable{\hbox\bgroup \catcode\|=12 \vtabledefs \tableB}
\def\tableB#1#2{\offinterlineskip \def\tmpa{}\tabdata={}\scantabdata#1\relax
\valign\expandafter{\the\tabdata\tabstrutA\cr#2\crcr}\egroup}
\def\vtabledefs{%
\let\dopar=\hfilneg  % the items of paragraph format are prefixed by \dopar
\def\setrowparams{\hsize=\dimen\tmpnum \leftskip=.5em \rightskip=\leftskip
\normalbaselines \hsize=\tmpdim
\emergencystretch=2em \noindent\hfil}%
\def\topstrut{\vbox to3ex{}}\def\botstrut{\vtop to2ex{}}%
\def\tabstrut{}%
\def\crl{\crcr\noalign{\vrule}}%
\def\colw=##1 {\noalign{\global\tmpdim=##1}}%
\def\crli{\crcr \omit \gdef\dditem{\omit\tablinefil}\gdef\vvitem{\tabvvline}%
\vvleft\tablinefil\ddlinedata\cr}%
\def\tabvvline{\hrule\kern\hhkern\hrule}%
\def\crlli{\crli\noalign{\kern\vvkern}\crli}%
\tmpdim=100pt
\def\tabdeclarec{\medskip\vfil\vbox{\setrowparams\topstrut####\unskip\botstrut}\vfil\medskip}%
}
\def\vvkern{2pt} \def\hhkern{4pt}

\def\multirow#1#2{\multispan{#1}\vfil\vbox{\setrowparams\topstrut#2\botstrut}\vfil}%

\def\crx{\crcr\noalign{\hskip\hhkern\hskip\hhkern}}

% document:

\def\blah{blah blah blah blah blah blah blah blah}
\def\blahh{\blah\ \blah\ \blah\  blah blah blah}

\def\itemcolors#1#2#3#4#5{\colitem#1&\colitem#2&\colitem#3&\colitem#4&\colitem#5\crc}

\def\liRed{\setcmykcolor{0 .5 .5 0}}
\def\liBlue{\setcmykcolor{.3 .3 0 0}}
\def\liGreen{\setcmykcolor{.5 0 .5 0}}
\def\liOrange{\setcmykcolor{0 0.2 0.5 0}}
\def\liCyan{\setcmykcolor{.3 0 0 0}}

\vtable{ccccc}{
\colw=20mm \colitem\liGreen & \colitem\liGreen & \spancolor3\liOrange \crc
Type  & & \multirow3{Spring} \crx
\colw=20mm \itemcolors\liRed\liBlue\liRed\liBlue\liRed
Specs & Model 1 & Model 2 & Model 3 & Model 4 \crx
\colw=40mm \itemcolors\liCyan\Yellow\liCyan\Yellow\liCyan
Uses  & \dopar\blah & \dopar\blahh & \dopar\blah & \dopar\blah\ blah \crx
}
\bye


-

Here's a LaTeX solution:

\documentclass{article}
\usepackage{array,multirow}

\newcommand*\blah{blah blah blah blah }

\newcolumntype{z}[1]{>{\centering\arraybackslash}m{#1}}% a centered m-type column
\renewcommand*\multirowsetup{\centering}% default is \raggedright

\begin{document}

\begin{tabular}{|z{2cm}|z{2cm}|m{.3\linewidth}|}
\firsthline
\bfseries Type &
\multicolumn{1}{c|}{\bfseries Specs} &
\multicolumn{1}{c|}{\bfseries Uses} \\
\hline
& Model 1 & \blah\blah \\
\hline
\multirow{3}*[-2\baselineskip]{Spring}
& Model 2 & \blah\blah\blah\blah\blah blah blah blah \\
\cline{2-3}
& Model 3 & \blah\blah \\
\cline{2-3}
& Model 4 & \blah\blah blah blah blah \\
\lasthline
\end{tabular}

\end{document}


The »Spring« in the \multirow needed some vertical shift (the optional argument [-2\baselineskip]). If this is necessary depends on the actual use case and is explained in the manual.

Even easier and without the need for manual interference is using nested tabulars. We just need to suppress the space to the left and right of the inner tabular by inserting @{} to the column specs:

\documentclass{article}
\usepackage{array}

\newcommand*\blah{blah blah blah blah }

\newcolumntype{z}[1]{>{\centering\arraybackslash}m{#1}}

\begin{document}

\begin{tabular}{|z{2cm}|z{2cm}|m{.3\linewidth}|}
\firsthline
\bfseries Type &
\bfseries Specs &
\multicolumn{1}{c|}{\bfseries Uses} \\
\hline
& Model 1 & \blah\blah \\
\hline
Spring &
\multicolumn{2}{@{}c@{}|}{%
\begin{tabular}{z{2cm}|m{.3\linewidth}}
Model 2 & \blah\blah\blah\blah\blah blah blah blah \\
\hline
Model 3 & \blah\blah \\
\hline
Model 4 & \blah\blah blah blah blah \\
\end{tabular}%
} \\
\lasthline
\end{tabular}

\end{document}


The output is the same.

-
Thank you for LaTeX solution. But the main point of this thread is that we need to calculate the position of "Spring" automatically because we don't know how many blahs will be in the third column. –  wipet Jul 8 '14 at 10:14
@wipet that isn't entirely clear from the question: »How to create the following table«. I did look if this was required by your question but couldn't find it... I don't believe there is a ready made solution then in LaTeX –  clemens Jul 8 '14 at 10:20
@wipet I added a second solution that doesn't need manual adjusting –  clemens Jul 8 '14 at 11:58