2

Tables are the final frontier of my documents. So far I have managed to standardized over 20 documents (hundreds of pages) using a single, shared preamble.

Issue

Abstracting format from content in tables still eludes me.

I have limited my tables to two major types and one minor type.

Table List

  • tabular
  • longtable
  • tabularx (being weeded out for consistency. It is still a nice option)

I use LaTeX for its ability to separate formatting from content. Tables seems to have two much non-content code integrated inside of them

  • \hline
  • \toprule, \midrule, \bottomrule from booktabs
  • manually setting alignment of cells, rows, and columns per table (annoying, should be global with option to override locally)
  • having to set colors and other formatting of header cells, rows, and columns per table (should be global with option to override locally)
  • having to set colors and other formatting of data cells locally, rows, and columns per table (should be global with option to override locally)
  • although probably not avoidable, multirow and multicolumn must be inside the data.

Complete This List

Things that offer global conditions for all of the tables in Table List:

  • pgfplotstable
  • ?

In an ideal world, I could do something like the following and they would function as specified in the preamble (without any local adjustments):

\begin{mycustomtabular}
col1 & col2 & col3 \\
dat1 & dat2 & dat3 \\
dat4 & dat5 & dat6 \\
\end{mycustomtabular}

\begin{mycustomtabular}
col1 & col2 & col3 & col4 \\
dat1 & dat2 & dat3 & dat4 \\
dat5 & dat6 & dat7 & dat8 \\
\end{mycustomtabular}

\begin{mycustomtabular}[longtable] % set to use longtable
col1 & col2 & col3 & col4 \\
dat1 & dat2 & dat3 & dat4 \\
dat5 & dat6 & dat7 & dat8 \\
\end{mycustomtabular}

Update 2015-04-13

I was able to format a column, but not yet globally with the following code.

**A step in the right direction, but still missing the ability to add two things globally:

  • \rowstyle{\bfseries\Large\color{green!25!gray}} (this works with NewEnviron + tabularx)
  • \midrule
  • (ignoring issues with referencing cells for the time being)

Code

\documentclass{article}
\usepackage{fontspec}
\usepackage{booktabs} % Adds support for \toprule, \midrule, \bottomrule
\usepackage{xcolor} % Adds support for coloring blocks of text: \color{green!25!black} or \textcolor{green!25!black){text}
  \usepackage{tabularx}
 \usepackage{environ} % Use for tabular environment when using booktabs
\usepackage{array} % https://tex.stackexchange.com/a/4816/13552
\newcolumntype{$}{>{\global\let\currentrowstyle\relax}}
\newcolumntype{^}{>{\currentrowstyle}}
\newcommand{\rowstyle}[1]{\gdef\currentrowstyle{#1}%
  #1\ignorespaces
}

\newenvironment{mytab}[1][$l*{50}{^l}]{% <-- tabular WORKS!
  \begin{tabular}{#1}\toprule}{%
  \rowstyle{\bfseries\color{green}} %<-- Global \rowstyle
  \\\bottomrule\end{tabular}}


  \newenvironment{mytabx}[1][$l*{50}{^l}]{% <-- tabularx WORKS!
    \tabularx{\linewidth}{#1}\toprule}{%
  \\\bottomrule\endtabularx}


\NewEnviron{mysupertabx}[1][$l*{50}{^l}]{% <-- tabularx with NewEnviron
  \tabularx{\linewidth}{#1}\toprule\rowstyle{\bfseries\color{green!25!gray}}\BODY\bottomrule}{% <-- Global formatting on first row WORKS!
 \endtabularx}

\begin{document}
\begin{table}
\begin{mytab}
\rowstyle{\bfseries\Large\color{green!25!gray}} %<--- Commenting this line out should make global \rowstyle apply
col1 & col2 & col3 & col4 \\ \midrule
dat1 & dat2 & dat3 & dat4 \\
dat5 & dat6 & dat7 & dat8 \\
\end{mytab}
\caption{Tabular without working global row style or global centering}
\end{table}
\begin{table}
\begin{mytabx}[$l^X^l^l] % <-- tabularx with local override WORKS but with an issue (see output)!
\rowstyle{\bfseries\color{green!25!gray}} %<--- Commenting this line out should make global \rowstyle apply
col1 & col2 & col3 & col4 \\ \midrule
dat1 & dat2 & dat3 & dat4 \\
dat5 & dat6 & dat7 & dat8 \\
\end{mytabx}
\caption{Tabularx with messed up first row}
\end{table}
\def\tabularxcolumn#1{m{#1}} % Redefines tabularx X row to vertically center text
\begin{table}
\begin{mytabx}[$l^X^l^l] % <-- tabularx with local override WORKS but with an issue (see output)!
\rowstyle{\bfseries\color{green!25!gray}} %<--- Commenting this line out should make global \rowstyle apply
col1 & col2 & col3 & col4 \\ \midrule
dat1 & dat2 & dat3 & dat4 \\
dat5 & dat6 & dat7 & dat8 \\
\end{mytabx}
\caption{Tabularx inside newenvironment with fixed first row (column redefinition) but broken bottomrule.}
\end{table}
\begin{table}
\begin{mysupertabx}[$l^X^l^l] % <-- tabularx with local override WORKS but with an issue (see output)!
%\rowstyle{\bfseries\color{green!25!gray}} %<--- Commenting this line out should make global \rowstyle apply and in this case it WORKS!
col1 & col2 & col3 & col4 \\ \midrule
dat1 & dat2 & dat3 & dat4 \\
dat5 & dat6 & dat7 & dat8 \\
\end{mysupertabx}
\caption{Tabularx inside NewEnviron from environ package with working global formatting for first row. Midrule must still be explicitly inputted into the tabular data :(}
\end{table}


\end{document}

Tabular Output

enter image description here

Tabularx with Local Override Output

The fix for this is found here: https://tex.stackexchange.com/a/105671/13552 enter image description here

Full Output

enter image description here

Disclaimer: I realize that this question does not target a specific problem (rather an issue with tables), but if it is alright, I think it is more useful than my favorite question: How can I explain the meaning of LaTeX to my grandma?

  • 1
    Regarding the alignment: Use the \newcolumntype command from array and define some 'general' column types which can be customized... an idea, not checked – user31729 Apr 8 '15 at 7:47
  • In ConTeXt, natural tables and xtables satisfy all the criteria. – Aditya Apr 8 '15 at 13:06
  • You might find my package cals useful. The only thing it lacks is per-column formatting. ctan.org/pkg/cals – olpa Apr 9 '15 at 13:36
6

It's not clear that there is really an issue to be solved, it is only an issue for tables if you think there is an issue about tables. Most of the points that you raise could also be made about "paragraphs" or "lists", at some point you have to have some structural information as well as words.

It is easy to have an environment that defaults the column spec, consider for example the amsmath matrix which is more or less just array with a default supplied preamble of *{20}{c} so you could define

\newenvironment{mytab}[1][*{50}{c}]{%
  \begin{tabular}{#1}}{%
  \end{tabular}}

which makes the column specifications optional, defaulting to all centred. Unlike matrices though where a global default is commonly useful, in my experience a global table default is almost never useful, tables usually have varied column types, some textual, some numeric to be aligned on decimal points, etc. However if in a particular document you have a lot of tables all taking the same form you could use a definition as above, replacing *{50}{c} by say >{\bfseries}l *{2}{D..{3.2}} p{3cm} if all your tables have a bold left aligned column, two numeric columns and a final column of note paragraphs.

It's hard to guess how you could automate rules in general, If you always want a top and bottom rule you could change your definition to

\newenvironment{mytab}[1][*{50}{c}]{%
  \begin{tabular}{#1}\toprule}{%
  \\\bottomrule\end{tabular}}

But the position of \midrule is rather like the position of words and numbers in the table, effectively it's data that must be entered in each case. Perhaps you only want \midrule after the heading in which case you could use

\newcommand\endhead{\\\midrule}

so your tables would then look like

\begin{mytab}
\hd{type}&\hd{A}&\hd{B}&\hd{Notes}\endhead
zzz&1.2&3.4& zz zz zzzzz\\
zzz&1.2&3.4& zz zz zzzzz\\
\end{tab}

Using a heading command \hd that could be defined as

\newcommand\hd[1]{%
 \multicolumn{1}{c}{\bfseries\begin{tabular}{@{}c@{}}#1\end{tabular}}

To give bold, centred, potentially multi-line table headings. Color could be added to this command as well if you want coloured tables, there is no need for explicit colours in the table.

  • A good discussion of the yin and yang of automation vs. flexibility. – Steven B. Segletes Apr 8 '15 at 9:51
  • @DavidCarlisle I can affect the first paragraph after every section globally (e.g. remove indent globally) but not a table's first row (inject \midrule globally). It would be nice to be able to inject code per cell, row, or column. Would it be practical to create a new command for each & and \\ and apply a counter to them, such that other code can be injected at reference end of row 1 (when rowCounter=1)? – Jonathan Komar Apr 8 '15 at 11:28
  • @macmadness86 yes (easy for \\ harder to do it for & (or at least it's likely to have more compatibility issues for &) \\ is already a macro rather that a TeX primitve row end (which is \cr) so it can easily be defined to do anything you want. the xcolor \rowcolor extensions already has such a counter which it checks for odd/even to decide the colour to use. You can't really make global changes to paragraphs, it's just that you can define the command \section{} to affect the immediately following paragraph. – David Carlisle Apr 8 '15 at 11:39
  • @DavidCarlisle Do you think you could provide a quick explanation for what is happening with *{50}{c}. That is the default variable input, but what does it do (I already tried making it *{1}{c} expecting it to fail, and it did indeed fail.) – Jonathan Komar Apr 8 '15 at 19:14
  • 1
    yes but there are special rules for how to refer to tabularx in an environment definition, see the manual, basically you need \tabularx not \begin{tabularx} (same rules as ams alignments, for same reason, mostly) – David Carlisle Apr 13 '15 at 12:11

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.