15

I would like to be able to define a macro that can be used in the tabular definition. How can I do this?

This does not work:

\documentclass{article}

\begin{document}
\gdef\buildtabularhead{|||}

\begin{tabular}{\buildtabularhead}
1 & 2 &3\\
\end{tabular}
\end{document}

7 Answers 7

11

This is probably not practical but it's a nice demonstration of \expandafter and gets around the problem of macros in the table preamble with the array package.

\documentclass{article}
\usepackage{array}
\begin{document}
\def\buildtabularhead{|c|c|c|}
\expandafter\tabular\expandafter{\buildtabularhead}
1 & 2 &3\\
\endtabular
\end{document}

The two \expandafters make sure that the macro \buildtabularhead is expanded before LaTeX knows it should be expecting a tabular preamble. Notice also that instead of \begin{tabular}...\end{tabular} I had to use \tabular...\endtabular. Internally the former does the same as the latter but surrounding it with a group and doing important checks, including proper nesting (See source2e Section 54.1).

19

Better define it as a new column type using the array package:

\documentclass{article}
\usepackage{array}
\newcolumntype{L}{|l|l|l|}
\begin{document}

\begin{tabular}{L}
1 & 2 &3\\
\end{tabular}
\end{document}
7

I had a very dirty answer, but I found theneater solution below while reading the documentation of the array package. In particular, this is inspired from how the * column specifier is defined there.

The idea is to introduce the new column type \expand (\newcolumntype sets up most of the necessary ingredients), and then redefine \NC@rewrite@\expand to expand the next token with \expandafter, and then continue the action that array is doing at that time (namely finding user-defined column types and replacing them by their definition).

\documentclass{article}
\usepackage{array}

\makeatletter
\newcolumntype{\expand}{}
\long\@namedef{NC@rewrite@\string\expand}{\expandafter\NC@find}
\makeatother

\begin{document}
\def\mypream{c|*{2}{c|||}}
\begin{tabular}{c\expand\mypream cc}
    a   & b   & d     &e   & f     & apsdoi \\
    cde & def & erasd &arp & sefoi & wp     
\end{tabular}
\end{document}
6
  • Can I use this solution if \mypream has a parameter? I tried using \expand{\mypream{something}} but that doesn't seem to work. Commented Sep 2, 2014 at 17:36
  • I haven't tested, but I'd expect \expand\mypream{something} to work. Commented Sep 2, 2014 at 18:32
  • It doesn't. Perhaps I should ask a new question. Commented Sep 3, 2014 at 7:38
  • It does. To test, I just replaced the definition of \mypream by \def\mypream#1{#1|*{2}{#1|||}} and replaced c\expand\mypream cc by c\expand\mypream{c}cc, and got the correct tabular. Commented Sep 3, 2014 at 9:55
  • Oh. You can add your solution to my question. Commented Sep 3, 2014 at 9:57
6

It does work when you correct your tabular header.

\documentclass{article}

\def\buildtabularhead{|c|c|c|}

\begin{document}
\begin{tabular}{\buildtabularhead}
  1 & 2 & 3 \\
\end{tabular}
\end{document}
3
  • 2
    Note that this solution won't work if you are using the array package or any other package that loads it.
    – Alan Munn
    Commented Feb 27, 2011 at 18:06
  • @Alan @Christian I am using the array package! Is their a way to by-pass the issue?
    – yannisl
    Commented Feb 27, 2011 at 18:13
  • 3
    @salty Yes, use Martin's solution of defining a new column type. It achieves exactly the same aim but just slightly differently.
    – Alan Munn
    Commented Feb 27, 2011 at 18:15
5

The column definition, you are using as an example is invalid. It only specifies lines and no real columns. If you change it to something like \gdef\buildtabularhead{|c|c|c|} it works as expected.

2
  • still gives me an error Illegal pream-token
    – yannisl
    Commented Feb 27, 2011 at 18:07
  • @saltypen: At Alan Munn pointed out above this doesn't work when the array package is loaded (which is loaded by many other tabular related packages ...) Commented Feb 27, 2011 at 18:09
5

You can use the array package and still be able to specify the column specifiers through a macro as follows:

\documentclass{article}
\usepackage{array}
\begin{document}


\def\test#1{\newcolumntype{L}{#1}}
\test{clr}

\begin{tabular}{L}
1 & 2 &3\\
\end{tabular}
\end{document}

This can be useful, if you automating table generation through scripts.

6
  • 2
    Good answer (sorry out of votes for today), but X is a bad choice because it will collide with the tabularx package once loaded. Commented Feb 27, 2011 at 18:42
  • @Martin you right edited to `L', thanks.
    – yannisl
    Commented Feb 27, 2011 at 19:04
  • @Yiannis: Can you explain why you wrap the \newcolumntype in a macro? Commented Mar 1, 2011 at 14:10
  • @Hendrik Essentially because I wanted to pass a parameter. Lamport's original definition allowed the following \newcommand{\X}{clr} \begin{tabular}{\X} . . . The array package takes great care not to expand the preamble. By defining another macro you can make sure that the argument is expanded. In a more realistic application the \test macro would be used to set-up the tabular head programmatically. Another approach is to use expandafter as Mathew's fine answer demonstrates.
    – yannisl
    Commented Mar 1, 2011 at 19:52
  • @Yiannis: I'm not sure if I can follow. Would \test{\X} be any different from \newcolumntype{L}{\X}? Commented Mar 1, 2011 at 21:09
0

An alternative solution with tblr environment of tabularray package:

\documentclass{article}

\usepackage{tabularray}
\NewTblrEnviron{vlinetab}
\SetTblrInner[vlinetab]{vlines}

\begin{document}

\begin{vlinetab}{}
1 & 2 & 3 \\
4 & 5 & 6 \\
7 & 8 & 9 \\
\end{vlinetab}

\end{document}

enter image description here

You must log in to answer this question.

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