Define a table one column at a time instead of one row at a time

use two tabulars ...

\documentclass{article}

\begin{document}
\begin{tabular}[t]{|c}
    column 1, row 1 \\
    column 1, row 2 \\
    column 1, row 3 \\
    column 1, row 4 \\
    column 1, row 5 \\
\end{tabular}%
\begin{tabular}[t]{|c|}
    column 2, row 1 \\
    column 2, row 2 \\
    column 2, row 3 \\
    column 2, row 4 \\
    column 2, row 5 \\
\end{tabular}

\end{document}

The code below defines a vtab environment which reads its body (thanks to the environ package) and splits it into columns, and cells (using some LaTeX3 code), then puts it back together in rows rather than columns, and places its two arguments before and after the result. It is used as

\begin{vtab}{\begin{tabular}{cccc}}{\end{tabular}}
a\\b\\c\\d&
e\\f&
g\\h\\i&
j\\k\\l\\m\\n\\o
\end{vtab}

There are some comments in the code below, don't hesitate to ask. Earlier, I forgot the \ExplSyntaxOff line, which restores the normal TeX behaviour (spaces not ignored).

\RequirePackage{expl3}
\RequirePackage{environ}
\ExplSyntaxOn
% \NewEnviron defines |\begin{vtab}| to grab until |\end{vtab}|
% and store the result in |\BODY|. Then two steps.
% (1) Split |\BODY| into cells, storing them in a property list.
% (2) Read the property list in a different order, building the
% body of the tabular as we go.
% (3) Typesetting the tabular.
%
\NewEnviron { vtab } [2]
  {
    \TV_read:V \BODY
    \TV_build:
    \tl_put_left:Nn \l_TV_result_tl { #1 }
    \tl_put_right:Nn \l_TV_result_tl { #2 }
    \tl_use:N \l_TV_result_tl
  }

% We need some variables.
\int_new:N \l_TV_col_int
\int_new:N \l_TV_row_int
\int_new:N \l_TV_max_row_int
\prop_new:N \l_TV_cells_prop
\tl_new:N \l_TV_result_tl
\tl_new:N \l_TV_row_tl
\tl_new:N \l_TV_cell_tl

% Generic function to split a list with items delimited by a given token
% (in our application, either & or \\) and apply the third argument to
% each item that was found: this third argument will receive the item as
% |#1|. Used as |\TV_map_inline:nnn {\\} {a\\b\\c} {do #1}|.
%
% It is slightly tricky to get nesting to work (see e.g., explanations
% for |\clist_map_inline:nn| in |l3clist.dtx|).
%
\int_new:N \g_TV_map_inline_int
\cs_new_protected:Npn \TV_map_inline:nnn #1 #2 #3
  {
    \tl_if_empty:nF {#2}
      {
        \cs_gset_eq:cN
          {TV_map_inline_\int_use:N \g_TV_map_inline_int :w}
          \TV_map_inline_aux:w
        \int_gincr:N \g_TV_map_inline_int
        %
        \cs_gset:Npn \TV_map_inline_aux:w ##1 #1 
          {
            \quark_if_recursion_tail_stop:n {##1}
            #3
            \TV_map_inline_aux:w
          }
        \TV_map_inline_aux:w #2 #1 \q_recursion_tail #1 \q_recursion_stop
        %
        \int_decr:N \g_TV_map_inline_int
        \cs_gset_eq:Nc
          \TV_map_inline_aux:w
          {TV_map_inline_\int_use:N \g_TV_map_inline_int :w}
      }
  }

% We split into columns first |&|, then rows |\\|. While doing this,
% we keep track of the index of the row and column, and what the
% highest row number is (this will be the number of rows in the
% resulting tabular). The cell's content is stored as the property
% "row,column" in |\l_TV_cells_prop|.
%
\cs_new:Npn \TV_read:n #1
  {
    \int_zero:N \l_TV_col_int
    \int_zero:N \l_TV_max_row_int
    \TV_map_inline:nnn {&} {#1}
      {
        \int_incr:N \l_TV_col_int
        \int_zero:N \l_TV_row_int
        \TV_map_inline:nnn {\\} {##1}
          {
            \int_incr:N \l_TV_row_int
            \exp_args:NNx \prop_put:Nnn \l_TV_cells_prop
              { \int_use:N \l_TV_row_int , \int_use:N \l_TV_col_int }
              { ####1 }
          }
        \int_compare:nT { \l_TV_row_int > \l_TV_max_row_int }
          { \int_set_eq:NN \l_TV_max_row_int \l_TV_row_int }
      }
  }
\cs_generate_variant:Nn \TV_read:n {V}

% To build, loop for |##1| from 1 to the number of rows,
% and for |####1| from 1 to the number of columns, and extract
% the relevant cell, then place it in the relevant row.
% The funny |\use_none:n| business removes the first |&| from
% each row as it is added to the result.
\cs_new:Npn \TV_build:
  {
    \tl_clear:N \l_TV_result_tl 
    \prg_stepwise_inline:nnnn {1} {1} { \l_TV_max_row_int }
      {
        \tl_clear:N \l_TV_row_tl
        \prg_stepwise_inline:nnnn {1} {1} { \l_TV_col_int }
          {
            \prop_pop:NnNF \l_TV_cells_prop { ##1 , ####1 } \l_TV_cell_tl
              { \tl_clear:N \l_TV_cell_tl }
            \tl_put_right:Nx \l_TV_row_tl { & \exp_not:V \l_TV_cell_tl }
          }
        \exp_args:NNf \tl_put_right:Nn \l_TV_result_tl
          { \exp_after:wN \use_none:n \l_TV_row_tl \\ }
      }
  }
\ExplSyntaxOff % [EDIT: added that line]
\documentclass{article}
\begin{document}
\begin{vtab}{\begin{tabular}{cccc}}{\end{tabular}}
a\\b\\c\\d&
e\\f&
g\\h\\i&
j\\k\\l\\m\\n\\o
\end{vtab}
\end{document}

Here is a plain-tex version using \valign, adapted from TH.'s awesome answer.

\valign{&\hbox spread1em{\strut#\hfil}\cr
column 1, row 1 & column 1, row 2 & column 1, row 3 & column 1, row 4 \cr
column 2, row 1 & column 2, row 2 & column 2, row 3 & column 2, row 4 \cr}
\bye

Tags:

Columns

Tables