6

I am trying to define a command for tabular entries using keyval.

\documentclass{article}

\usepackage{keyval}

\makeatletter
\define@key{tabularEntryKeys}{a}[\dots]{#1 & }
\define@key{tabularEntryKeys}{b}[\dots]{#1   }
\makeatother

\newcommand{\tabularEntry}[1]{\setkeys{tabularEntryKeys}{#1}}

\begin{document}

\begin{tabular}{c|c}\hline
  \tabularEntry{a=1,b=2} % shall be "1 & 2"
\end{tabular}

\end{document}

However it does not compile. Any suggestions?

4 Answers 4

3

Here is one more approach. It does neither global definitions nor use of e-TeX extensions and \edef.

tabularkeys

\documentclass{article}

\usepackage{keyval}
\def\TAB{&}

\makeatletter
\define@key{tabularEntryKeys}{a}[\dots]{\def\tek@rowA{#1}}
\define@key{tabularEntryKeys}{b}[\dots]{\def\tek@rowB{#1}}
% initialize
\def\tek@rowA{}
\def\tek@rowB{}

\newcommand{\tabularEntry}[1]{\setkeys{tabularEntryKeys}{#1}%
                              \tek@rowA \expandafter\TAB\tek@rowB }
\makeatother

\begin{document}

\begin{tabular}{c|c}
\hline
  \tabularEntry{a=1,b=2} \\
  \tabularEntry{a=1} \\
  \tabularEntry{b=2} \\
  \tabularEntry{a,b} \\
  \tabularEntry{a} \\
  \tabularEntry{b} \\
  \tabularEntry{} \\
\end{tabular}
% \begin{tabular}{c|c}\hline
%   \tabularEntry{a=1,b=2}\\
%   \tabularEntry{a=3,b=7}\\
%   \tabularEntry{a=10,b=20}
% \end{tabular}

\end{document}

In case of more cells in one row, one needs a variant to avoid many many \expandafter's: (notice the extra spaces added before #1 and in the initial defaults values except for \tek@rowA and \tekrowD)

\usepackage{keyval}
\def\TAB{&}
\makeatletter
\define@key{tabularEntryKeys}{a}[\dots]{\def\tek@rowA{#1}}
\define@key{tabularEntryKeys}{b}[\dots]{\def\tek@rowB{ #1}}
\define@key{tabularEntryKeys}{c}[\dots]{\def\tek@rowC{ #1}}
\define@key{tabularEntryKeys}{d}[\dots]{\def\tek@rowD{#1}}
% initialize
\def\tek@rowA{}
\def\tek@rowB{ }
\def\tek@rowC{ }
\def\tek@rowD{}

\newcommand{\tabularEntry}[1]{\setkeys{tabularEntryKeys}{#1}%
     \tek@rowA \expandafter\TAB
     \romannumeral0\expandafter\tek@rowB\expandafter\TAB
     \romannumeral0\expandafter\tek@rowC\expandafter\TAB
     \tek@rowD 
}
\makeatother
3
  • If you use something like -`Q instead of 0 you won't need the extra spaces.
    – egreg
    May 24, 2014 at 19:16
  • @egreg no sorry, this wouldn't work: first I would still need to leave the spaces in the initial default values; second b=\empty would create an error. In both cases the cause of the error is premature expansion of \TAB.
    – user4686
    May 24, 2014 at 21:46
  • @egreg but thanks for the input. I do use \romannumeral-`0 at some places in xint, for example in things \romannumeral-`0#1\relax.
    – user4686
    May 24, 2014 at 22:02
4

Here is how it works:

\documentclass{article}

\usepackage{keyval}    

\makeatletter
\define@key{tabularEntryKeys}{a}[\dots]{\gdef\A{#1}}
\define@key{tabularEntryKeys}{b}[\dots]{\gdef\B{#1}}
\makeatother

\newcommand\tabularEntry[1]{\setkeys{tabularEntryKeys}{#1} \A & \B}

\begin{document}

\begin{tabular}{c|c}\hline
    \tabularEntry{a=1,b=2}
\end{tabular}

\end{document}
4
  • 1
    moreover \tabularEntry {b=2,a=1} will also work in this approach, whereas the OP's code could not, even if the scope closing nature of & in a tabular was avoided.
    – user4686
    May 24, 2014 at 15:05
  • Sorry, no, but this is wrong under many respects. For instance, if you specify a new row as \tabularEntry{b=3}, the previous value given to a will appear.
    – egreg
    May 24, 2014 at 16:00
  • @egreg, in this case it's not a bug, it's a feature. a is repeating several times.
    – sergej
    May 24, 2014 at 16:18
  • @sergej This doesn't appear in your question.
    – egreg
    May 24, 2014 at 16:25
2

Your \setkeys command can't straddle two cells. On the other hand globally defining \A and \B doesn't seem a good idea.

\documentclass{article}

\usepackage{keyval,etoolbox}    

\makeatletter
\define@key{tabularEntryKeys}{a}[\dots]{\def\tek@rowA{\unexpanded{#1}}}
\define@key{tabularEntryKeys}{b}[\dots]{\def\tek@rowB{\unexpanded{#1}}}
% initialize
\def\tek@rowA{}
\def\tek@rowB{}
\newcommand\tabularEntry[1]{%
  \setkeys{tabularEntryKeys}{#1}%
  \edef\tek@row{\tek@rowA & \tek@rowB}\tek@row
}
\makeatother

\begin{document}

\begin{tabular}{c|c}
\hline
  \tabularEntry{a=1,b=2} \\
  \tabularEntry{a=1} \\
  \tabularEntry{b=2} \\
  \tabularEntry{a,b} \\
  \tabularEntry{a} \\
  \tabularEntry{b} \\
  \tabularEntry{} \\
\end{tabular}

\end{document}

Note that the optional argument in \define@key is the value assigned to the key when the key is specified without =<value> following, not an initial value.

enter image description here

If you want the values to repeat if a key is not specified, then say

\define@key{tabularEntryKeys}{a}[\dots]{\gdef\tek@rowA{\unexpanded{#1}}}
\define@key{tabularEntryKeys}{b}[\dots]{\gdef\tek@rowB{\unexpanded{#1}}}

but don't use “easy” macro names such as \A or \B.

0

This is an easy task using the expkv-cs package as it is fully expandable (so doesn't care for the implicit group added at & as it doesn't need any definitions which could be limited by that scope) and can split a key=value argument into several numbered parameters.

One can define a new splitting macro with

\ekvcSplit\tabularEntry{a=,b=}{#1&#2}

This will define the macro with two keys, both being empty arguments if they aren't used. To get \dots if one uses the key without a value we have to define those defaults with

\ekvcSecondaryKeys\tabularEntry{default a = \dots, default b = \dots}

The complete code would look like this:

\documentclass{article}

\usepackage{expkv-cs}

\ekvcSplit\tabularEntry{a=,b=}{#1&#2}
\ekvcSecondaryKeys\tabularEntry{default a=\dots, default b=\dots}

\begin{document}

\begin{tabular}{c|c}\hline
  \tabularEntry{a=1,b=2} \\
  \tabularEntry{a=1} \\
  \tabularEntry{b=2} \\
  \tabularEntry{a,b} \\
  \tabularEntry{a} \\
  \tabularEntry{b} \\
  \tabularEntry{} \\
\end{tabular}

\end{document}

And the results:

enter image description here

You must log in to answer this question.

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