12

Is there a way to define a table like so?

\begin{tabular}{|c|c|}
    column 1, row 1 \\
    column 1, row 2 \\
    column 1, row 3 \\
    column 1, row 4 \\
    column 1, row 5 \\ &&
    column 2, row 1 \\
    column 2, row 2 \\
    column 2, row 3 \\
    column 2, row 4 \\
    column 2, row 5 \\
\end{tabular}

I'm flexible as to how it's done, I would just like to be able to define a whole column at a time (as each column's entries are highly inter-related, and not as much from row to row).

11
  • The tabular environment uses the plainTeX \halign primitive internally which needs the row-by-row format. This can't be changed. One funny idea would be to turn every cell 90degrees and then the whole table 90degr backwards, making effectively rows to columns and vice versa. However, then the cell alignment (c, l, r, ..) would not work as usual of course. Commented Jul 3, 2011 at 21:39
  • @Martin, Nate: \halign's counterpart is \valign which switches cols to rows, there's some rather nice examples of its use here in this site.
    – morbusg
    Commented Jul 4, 2011 at 4:37
  • @morbusg: I know \valign but you can't just say {\let\halign\valign\begin{tabular}{..} .., can you? Commented Jul 4, 2011 at 5:15
  • @Martin: oh, right, I didn't think quite that far. Merely, your description rang a bell. :-)
    – morbusg
    Commented Jul 4, 2011 at 7:14
  • 1
    I tried the three proposed methods. All of them work. Great examples. But, with the second method, the spaces betwen words are compressed. I added a title and text between the tables and observed that there aren't enough vertical space between tables and paragraphs. Probably an incorrect apreciation of mine, but the visual appearance is of a table too close to the text. Also, with the second method, the paragraphs does not wraps at the margin.
    – djnavas
    Commented Jul 6, 2011 at 22:48

3 Answers 3

9

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}
4
  • 1
    Shame on me for not thinking of the obvious thing ;^). Obviously, these are two separate tables, so is there any way to set equal rubber column widths, like with tabularx's X? Or is the only option to set explicit widths with p{}?
    – Nate
    Commented Jul 3, 2011 at 22:48
  • Actually, while I'm at it - is there a way to balance the number of rows across tables? Not all of my columns have the same number of rows, but (obviously) the \hlines at the bottom all need to line up.
    – Nate
    Commented Jul 3, 2011 at 23:13
  • @Nate: then use [b] instead of [t] to align the tabulars at the bottom.
    – user2478
    Commented Jul 4, 2011 at 6:59
  • Ah, I guess I wasn't specific enough - I meant that I wanted both the top and the bottom to line up. I.e., some way to say "make these two tables the same height". For now it's not that big of a deal... I just put in filler.
    – Nate
    Commented Jul 4, 2011 at 18:38
4

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}
3

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
9
  • Do you think that this could be used as a basis for a tabular-like environment? (I tried, but failed) Commented Jul 5, 2011 at 22:53
  • @morbusg - Now, how do you include borders as nice as the ones in tabular? I couldn't get it to do \hlines at all.
    – Nate
    Commented Jul 6, 2011 at 13:15
  • @Bruno: I'm sorry to say I haven't yet got that far that I'd understand anything about LaTeX (I am still learning the primitives and plain-format). I did take a look at \def\tabular in latex.ltx, but I didn't really understand anything I saw. (lots and lots of @'s :-))
    – morbusg
    Commented Jul 6, 2011 at 13:51
  • @Nate: by borders do you mean rules around the whole construct? If so, you can just stuff the \valign inside a \fbox. (\fbox{\valign{...}})
    – morbusg
    Commented Jul 6, 2011 at 13:56
  • @morbusg: I understand. Tabulars in LaTeX are quite complicated. I'll ask "GL" (author of the tabu package, vary talkative on comp.text.tex) if he plans to do anything like that. Commented Jul 6, 2011 at 14:23

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .