# How to separate table content and table style

I want to know if there is a way to separate table / content for table style (think CSS).

Like to have only data specification

\begin{tabular}
H1 & H2 & H3 & h4 \\
V1 & V2 & V3 & V4 \\
\end{tabular}


And then have the style somewhere to have the heading bold, the line filled, etc.

-
Welcome to TeX.sx! Don't think CSS; LaTeX does not have a document object model. ConTeXt may get you closer (see wiki.contextgarden.net/Table) but still probably not what you are thinking about. – Matthew Leingang Mar 17 '11 at 18:05
@Matthew: I don’t get that: “Don’t think CSS” – why not? Separation of presentation and contents should be paramount in LaTeX and if someone would write a package to set tables in LaTeX in a sane way I would hail him as the new messiah. At the moment, tables in LaTeX suck. There’s nothing wrong in recognizing this. – Konrad Rudolph Mar 17 '11 at 19:28
Think CSS? Definitely. That is one of the most well known separations of content and presentation. Martin, i like your example. Thanks. – sbj3 Apr 27 '11 at 15:36

You can separate content and format in (La)TeX by defining your own logical format macros which are then (re)defined to the physical format macros required for each particular table.

For example the following table is used coded once but can be used with different styles. Normally the table might be in a user document or in a .tex file on its own and the styles could be placed in .sty files.

\documentclass{article}

\usepackage{array}
\usepackage{booktabs}

\newcommand\DEMOTABLE{%
V1 & V2 & V3 & V4 \\\normalline
V1 & V2 & V3 & V4 \\\normalline
V1 & V2 & V3 & V4 \\\lastline
\end{tabular}
}

\begin{document}

% Default
\newcolumntype{1}{l}
\newcolumntype{2}{l}
\newcolumntype{3}{l}
\newcolumntype{4}{l}
\newcommand*\normalline{}
\newcommand*\lastline{}

\par\bigskip\noindent
Default:\\[\smallskipamount]
\DEMOTABLE

% All rules
\newcolumntype{1}{|l}
\newcolumntype{2}{|l}
\newcolumntype{3}{|l}
\newcolumntype{4}{|l|}
\renewcommand*\normalline{\hline}
\renewcommand*\lastline{\hline}

\par\bigskip\noindent
Rules:\\[\smallskipamount]
\DEMOTABLE

% Nice looking rules, centered cells
\newcolumntype{1}{c}
\newcolumntype{2}{c}
\newcolumntype{3}{c}
\newcolumntype{4}{c}
\renewcommand*\normalline{}
\renewcommand*\lastline{\bottomrule}

\par\bigskip\noindent
Nice:\\[\smallskipamount]
\DEMOTABLE

\end{document}


### Result:

-
If really required it would be also possible to have the content only in an external file, i.e. only V1 & V2 & V3 & V4 \\ lines which are the processed by a special macro which adds the formatting macros automatically but this would be much more difficult. – Martin Scharrer Mar 17 '11 at 18:31
@Martin: I don't think it should be too difficult. It seems that \begin{tabular}{lc}\input{test.tex}\end{tabular} with a file test.tex of the form A&BB\\CC&D\\  works fine. – Bruno Le Floch Mar 17 '11 at 23:14
@Bruno: I meant to automatically had the required formatting macros. Ok, redefining \\ to mean \\\normalline wouldn't be difficult, but handling the first and last line special would be more difficult, etc. – Martin Scharrer Mar 17 '11 at 23:47
Do you think the inverse would be possible, having the style defined once, but to have some similar table with different content? – Olivier Toupin Mar 17 '11 at 23:59
@Olivier: Sure, as long you add the same general style macros to the other tables. However, changing it globally for all tables without adding such macros would be more difficult but in theory possible. – Martin Scharrer Mar 18 '11 at 0:22

ConTeXt makes this really easy. For example, to reproduce the example provided by Martin Scharrer, you can use

\startsetups table:default
\setupTABLE[each][each][width=2em, height=2em, align={middle,midddle}, frame=off]
\stopsetups

\startsetups table:framed
\setupTABLE[each][each][width=2em, height=2em, align={middle,midddle}, frame=on]
\stopsetups

\startsetups table:ruled
\setupTABLE[each][each][width=2em, height=2em, align={middle,midddle}, frame=off]
\setupTABLE[r][1][topframe=on, rulethickness=2bp]
\setupTABLE[r][2][topframe=on, rulethickness=0.5bp]
\setupTABLE[r][last][bottomframe=on, rulethickness=2bp]
\stopsetups

\starttext

% Change the argument to get different styles.
\startTABLE[setups=table:ruled]
\NC H1 \NC H2 \NC H3 \NC H4 \NC \NR
\NC V1 \NC V2 \NC V3 \NC V4 \NC \NR
\NC V1 \NC V2 \NC V3 \NC V4 \NC \NR
\NC V1 \NC V2 \NC V3 \NC V4 \NC \NR
\NC V1 \NC V2 \NC V3 \NC V4 \NC \NR
\stopTABLE

\stoptext

-
Anyway, to use ConTeXt and Latex at the same time? – Olivier Toupin Mar 21 '11 at 14:58
There are parts of backend ConTeXt code that is used in LaTeX (e.g., metapost to pdf conversion in pdftex and font loading in lualatex), but it is almost impossible to share front end code unless someone writes a macro level wrapper around either latex or context – Aditya Mar 21 '11 at 15:29
Then any package that's could provide similar functionnality in LaTex, the ConTexT syntax is exactly what's I was looking for, but I'm not sure it's worth the switch from ConText to LaTex, just for that. – Olivier Toupin Mar 21 '11 at 16:38
I don't know of a LaTeX package that does that. I would really like that also. – Aditya Mar 21 '11 at 20:01
@OlivierToupin see my answer :) – cmhughes Jan 11 '13 at 20:05

When it comes to style-based code, tikz and its derivatives lead the way. In terms of tables in TeX, the pgfplotstable seems to fit the bill perfectly for this question.

It has many, many different options, as detailed in the manual. The pgfplotstableset command can be used at any stage in the document- if used in the preamble as follows (for example), then it will apply the style to every occurrence of pgfplotstabletypeset

% global settings
\pgfplotstableset{
before row=\toprule,after row=\midrule},
every last row/.style={
after row=\bottomrule},
col sep = &,
row sep=\\,
string type,
}


Most of these options should be fairly self-explanatory; of course, these particular settings rely on loading the booktabs package. In the document, you now only have to type

\pgfplotstabletypeset{
person  & singEnglish & singGaeilge & pluralEnglish & pluralGaeilge\\
1st & at me       & agam        & at us         & againn\\
2st & agat        & at you      & agaibh        & other \\
3rd & at him      & aige        & at them       & acu\\
& at her      & aici        &               &\\
}


and you will get a beautiful table

If you choose to have your data separated by a comma (perhaps you're reading it from a file), then you override the settings locally:

\pgfplotstabletypeset[col sep=comma]{
person  , singEnglish , singGaeilge , pluralEnglish , pluralGaeilge\\
1st , at me       , agam        , at us         , againn\\
2st , agat        , at you      , agaibh        , other \\
3rd , at him      , aige        , at them       , acu\\
, at her      , aici        ,               ,\\
}


There are so many more options that you can play with, as detailed in the documentation, including using the array and colortbl packages.

A complete MWE follows

\documentclass{article}
\usepackage{booktabs}
\usepackage{pgfplotstable}

% global settings
\pgfplotstableset{
before row=\toprule,after row=\midrule},
every last row/.style={
after row=\bottomrule},
col sep = &,
row sep=\\,
string type,
}
\begin{document}

\pgfplotstabletypeset{
person  & singEnglish & singGaeilge & pluralEnglish & pluralGaeilge\\
1st & at me       & agam        & at us         & againn\\
2st & agat        & at you      & agaibh        & other \\
3rd & at him      & aige        & at them       & acu\\
& at her      & aici        &               &\\
}

\pgfplotstabletypeset[col sep=comma]{
person  , singEnglish , singGaeilge , pluralEnglish , pluralGaeilge\\
1st , at me       , agam        , at us         , againn\\
2st , agat        , at you      , agaibh        , other \\
3rd , at him      , aige        , at them       , acu\\
, at her      , aici        ,               ,\\
}

\end{document}

-

It is possible to insert automatically the macros that Martin uses in his solution, by using \aftergroup recursively. Somewhat tricky. In the code below, I define \newtabulartype, which allows you to define a tabular environment which treats specially the first row, and can have other rows treated specially. At the end of the day, a table can look as follows, with \Nobel, and \doubleNobel as semantic markup for physicist who won the prize. Changing plaintabular to coloredtabular changes the style with no need to change the body of the table.

\begin{plaintabular}
Surname        & First name       & Country & Dates            \\
Amp\ere       & Andr\'e-Marie    & France  & 1775--1836       \\
\AA ngstr\"om  & Anders Jonas     & Sweden  & 1814--1874       \\
Avogadro       & Amedeo           & Italy   & 1776--1856       \\
\doubleNobel Bardeen & John       & USA     & 1908--1991       \\
\Nobel Becquerel & Henri          & France  & 1852--1908       \\
Bell           & Alexander Graham & UK      & 1847--1922       \\
\Nobel Bethe   & Hans             & Germany, USA & 1906--2005  \\
Bhabha         & Homi J.          & India   & 1909--1966       \\
\end{plaintabular}


Then you can define one environment for each kind of tabular that you want to have, and changing the definition of that environment in the preamble will change the tables in your whole document consistently.

Here comes the code. Mostly the part with user commands is documented. The rest, not.

\documentclass{article}
\usepackage{array}
\usepackage{xparse}
\usepackage{booktabs}
\usepackage{colortbl}

\ExplSyntaxOn

% ===== Parsing the definition of a new table type.
% We find any "\repeat" and make sure that it is treated properly
% (not sure that it is...), then pass the result to
% \tabstyle_table_gset_aux:nnnnnn, which sets up the environment.
%
\cs_new:Npn \tabstyle_table_gset:nnnnnn #1 #2 #3 #4 #5 #6{
\tl_if_in:nnTF {#3}{\repeat} {
\tabstyle_table_gset_repeat:w #3 \q_stop
{\tabstyle_table_gset_aux:nnnnnn {#1} {#2}} {#4} {#5}{#6}
} {
\tabstyle_table_gset_aux:nnnnnn {#1}{#2}{#3}{#4}{#5}{#6}
}
}
\cs_new:Npn \tabstyle_table_gset_repeat:w #1 \repeat #2 \q_stop #3 {
#3 {#1 #2 \repeat #2}}
\cs_new:Npn \tabstyle_table_gset_aux:nnnnnn #1 #2 #3 #4 #5 #6 {
\renewenvironment{#1} #2 {
\g_tabstyle_restore_tl
#4
\tabular{#3} #5
}
{\tex_crcr:D#6\endtabular}
}

% ===== Doing rows
% Essentially the trick is \def\foo{\aftergroup\foo \foo}
% which repeats \foo in each cell. However, that needs to be stopped,
% and stopping it is not so easy. We redefine \\ to do that,
% but then, \\ must restore its previous definition afterwards.
% Also, \\ should not be assigned to globally, and we thus have to
% painfully reassign it at every cell (inside the definition of \foo,
% thus).
\tl_new:N \g_tabstyle_restore_tl
\cs_new:Npn \tabstyle_row_style_new:Nnnn #1 #2 #3 #4 {
\exp_args:Nno\newcommand{#1}{\cs:w tabstyle_row_the_\cs_to_str:N #1\cs_end:}
\cs_new:cpn {tabstyle_row_before_ \cs_to_str:N #1}{#2}
\cs_new:cpn {tabstyle_row_cell_ \cs_to_str:N #1}{#3}
\cs_new:cpn {tabstyle_row_after_ \cs_to_str:N #1}{#4}
\tl_gput_right:Nn \g_tabstyle_restore_tl {
\cs_gset:cpn {tabstyle_row_the_\cs_to_str:N #1} {
\tabstyle_row_first:N #1
}
}
}
\cs_new:Npn \tabstyle_row_first:N #1 {
\use:c{tabstyle_row_before_\cs_to_str:N #1}
\cs_gset:cpn {tabstyle_row_the_\cs_to_str:N #1} {\tabstyle_row_repeat:N #1}
\use:c{tabstyle_row_the_\cs_to_str:N #1}
}
\cs_new:Npn \tabstyle_row_repeat:N #1 {
\cs_set_eq:NN \tabstyle_old_newline: \\
\cs_set:Npx \\{
\exp_not:n {
\cs_gset:cpn {tabstyle_row_the_\cs_to_str:N #1} {
\tabstyle_row_restore:N #1}
\cs_set_eq:NN \\ \tabstyle_old_newline:
\\
}
\exp_not:c {tabstyle_row_after_\cs_to_str:N #1}
}
\exp_args:Nc \tex_aftergroup:D {tabstyle_row_the_\cs_to_str:N #1}
\int_compare:nT{\etex_currentgrouptype:D = 14}{
\use:c{tabstyle_row_cell_\cs_to_str:N #1}
}
\tex_ignorespaces:D
}
\cs_new:Npn \tabstyle_row_restore:N #1 {
\cs_gset:cpn {tabstyle_row_the_\cs_to_str:N #1} {\tabstyle_row_first:N #1}
}

% ======== Document Commands
% \newtabulartype{mytabular}[3][FOO]{crl} [<assignments>}{<first row>}{<end>}
% defines an environment, "mytabular", which takes three arguments:
% one optional, with default "FOO", and two mandatory. The next thing
% is the preamble, "crl" here, then <assignments> are local definitions
% which can change how the tabular will appear (executed before the
% beginnnig of the tabular), then a row type for the first line of the
% tabular, and finally, what to put at the end of the tabular.
%
\NewDocumentCommand{\newtabulartype}{ m l m O{} m m } {
\newenvironment{#1}{}{}
\tabstyle_table_gset:nnnnnn {#1}{#2}{#3}{#4}{#5}{#6}}
%
% A row style is defined by something to put before, something
% to put in each cell, and something to put at the end. And of course,
% the name, a single control sequence.
\NewDocumentCommand{\newrowstyle}{m m m m}{
\tabstyle_row_style_new:Nnnn #1{#2}{#3}{#4}}

% ======== Repeating columns
% These two lines allow repeated preambles, which I recommend when
% building a template for many tables (of varying sizes). Just
% put \repeat somewhere, and everything after that point will be
% repeated over and over again as much as is needed.
%
\newcolumntype{\repeat}{!{\span\tabstyle_repeat_from_here:}}
\cs_new:Npn \tabstyle_repeat_from_here: #1 & { #1 && }
% End of the "package" code.
\ExplSyntaxOff

% ==============================
% Defining the style of your tables goes as follows: define
% some row types, and then define an environment with a given
% setup. You can pass arguments to the tabular type, although I
% have not used it there.

% === Example
% First define a few styles for rows, here:
% - \plaintitlerow, simply bold face, for the header
% - \scshaperow, to get smallcaps
% - \strongrow, to get boldface.
\newrowstyle{\plaintitlerow}{}{\bfseries}{}
\newrowstyle{\scshaperow}{}{\scshape}{}
\newrowstyle{\strongrow}{}{\upshape\bfseries}{}
% Then setup the environment "plaintabular". No argument,
% the first column is in italics, and then we have the
% alignment rlrlrl, etc. Also, define that "\Nobel" should
% be smallcaps (style of row that we defined above), and
% "\doubleNobel" should be boldface. The title row is as
% defined above, in bold.
%
\newtabulartype{plaintabular}{>{\itshape}\repeat rl}
[\let\Nobel\scshaperow \let\doubleNobel\strongrow]
{\plaintitlerow}{}

% Second, a more fancy tabular. Define styles for rows,
% title with a \toprule and \midrule (see the booktabs package),
% and text typeset in \bfseries\large.
%
% Instead of using font changes, we can use colors, thanks to
% the colortbl package. In each cell of a line with
% \grayrow, place \cellcolor[gray]{0.8}. In each cell of
% a row with \bluerow, place the relevant color change.
% [Note that the colortbl package in fact provides a \rowcolor
% command, but this example is meant to showcase this code :D]
\newrowstyle{\nicetitlerow}{\toprule}{\bfseries\large}{\midrule}
\newrowstyle{\grayrow}{}{\cellcolor[gray]{0.8}}{}
\newrowstyle{\bluerow}{}{\cellcolor[rgb]{0.6,0.6,1}}{}
%
% Finally, we set up the tabular: first column in italics, centered,
% then repeatedly centered. We now define \Nobel to be in gray and
% \doubleNobel to be in blue, with the row types defined above.
% Also, the header will use the \nicetitlerow style, and we end the
% table with \bottomrule.
\newtabulartype{coloredtabular}{>{\itshape}c\repeat c}
[\let\Nobel\grayrow   \let\doubleNobel\bluerow]
{\nicetitlerow}{\bottomrule}

\begin{document}

% Two tables with the same content, different environments.
%
\begin{table}\centering
\begin{plaintabular}
Surname        & First name       & Country & Dates            \\
Amp\ere       & Andr\'e-Marie    & France  & 1775--1836       \\
\AA ngstr\"om  & Anders Jonas     & Sweden  & 1814--1874       \\
Avogadro       & Amedeo           & Italy   & 1776--1856       \\
\doubleNobel Bardeen & John       & USA     & 1908--1991       \\
\Nobel Becquerel & Henri          & France  & 1852--1908       \\
Bell           & Alexander Graham & UK      & 1847--1922       \\
\Nobel Bethe   & Hans             & Germany, USA & 1906--2005  \\
Bhabha         & Homi J.          & India   & 1909--1966       \\
\end{plaintabular}
\caption{Well known physicists. Nobel laureates are indicated
by small capitals. Bardeen received the prize twice. (These have been randomly chosen on the Wikipedia page \texttt{http://en.wikipedia.org/wiki/List\_of\_physicists}.)}
\end{table}

\begin{table}\centering
\begin{coloredtabular}
Surname        & First name       & Country & Dates            \\
Amp\ere       & Andr\'e-Marie    & France  & 1775--1836       \\
\AA ngstr\"om  & Anders Jonas     & Sweden  & 1814--1874       \\
Avogadro       & Amedeo           & Italy   & 1776--1856       \\
\doubleNobel Bardeen & John       & USA     & 1908--1991       \\
\Nobel Becquerel & Henri          & France  & 1852--1908       \\
Bell           & Alexander Graham & UK      & 1847--1922       \\
\Nobel Bethe   & Hans             & Germany, USA & 1906--2005  \\
Bhabha         & Homi J.          & India   & 1909--1966       \\
\end{coloredtabular}
\caption{Well known physicists. Colored rows correspond to Nobel laureates. (The choice of physicists is mostly arbitrary, among people cited in \texttt{http://en.wikipedia.org/wiki/List\_of\_physicists}.)}
\end{table}

\end{document}


If you want to grab the whole cell and apply some control sequence to it, rather than just changing font, you can use Martin Scharrer's collcell` package.

-