I want to automatically generate a table from a comma separated list of key-value pairs such as {{x=1,y=2},{x=3,y=1},{x=2,y=3}}
. In each "row" the "keys" are always the same (they become the column headers in the table), but the values can change. Given this particular list of key-value pairs the code below produces the following:
which is exactly what I want. Unfortunately marginally more complicated input for the values, such as {{x=1,y=$\overrightarrow{AB}$},{x=3,y=1},{x=2,y=3}}
, breaks my code. My code does generate the expected output:
but before it does this I get compilation errors such as:
! Illegal parameter number in definition of \tableRows. \crcr l.40 ...\overrightarrow{AB}$},{x=3,y=1},{x=2,y=3}}
Is there s a better/more robust way of doing this?
Here's my code:
\documentclass{article}
\usepackage{xparse,etoolbox}
\newcounter{tableRow} % for counting the number of rows in the table
\newcounter{tableCol} % for counting the number of columns
\newcommand\tableRows{} % to hold the contents of the table
\newcommand\tableHeader{} % to hold the header of the table
\newcommand\MakeTable[1]{
\setcounter{tableRow}{0} % initialise
\setcounter{tableCol}{1}
\renewcommand\tableRows{}
\renewcommand\tableHeader{}
\forcsvlist\ProcessRow{#1}% generate table
\begin{tabular}{*{\arabic{tableCol}}{c}}
\tableHeader\\\hline\tableRows\\
\end{tabular}
}
\makeatletter
\newcommand\ProcessRow[1]{% generate table rows using \ProcessEntry
\addtocounter{tableRow}{1}
\protected@xappto\tableRows{\Alph{tableRow}}% row label in table
\forcsvlist\ProcessEntry{#1}
\protected@xappto\tableRows{\\}
}
% need to extract key-value pairs from input of the form: key=val
\newcommand\ExtractKeyValuePair[2]{\def\Key{#1}\def\Value{#2}}
\DeclareDocumentCommand\ProcessEntry{>{\SplitArgument{1}{=}}m}{% add entries to row
\ExtractKeyValuePair#1% key-value pairs --> \Key and \Value
\ifnum\value{tableRow}=1%
\addtocounter{tableCol}{1}
\protected@xappto\tableHeader{&\Key}
\fi
\protected@xappto\tableRows{&\Value}
}
\begin{document}
\MakeTable{{x=1,y=2},{x=3,y=1},{x=2,y=3}}
% \MakeTable fails on this example
\MakeTable{{x=1,y=$\overrightarrow{AB}$},{x=3,y=1},{x=2,y=3}}
\end{document}
To generate the rows of the table I use \protected@xappto
from the etoolbox package. Initially I tried using tokens but I ran into expansion issues, due to my ignorance no doubt. It's not clear to me why I need \protected@xappto
, rather than\xappto
, but if I use \xappto
the code fails with both examples.
The way that I extract the key-value pairs also feels a little OTT: I am using some trickery with \SplitArgument
and \DeclareDocumentCommand
from the xparse package to do this.
EDIT
It turns out that my code mostly works and that I was a little unlucky in that \overrightarrow
was one of the first examples that I used in the real code that my MWE is distilled from. The problem with my MWE is that \overrightarrow
is a fragile command. I can fix the compilation error in the MWE by adding the lines:
\usepackage{fixltx2e}
\MakeRobust{\overrightarrow}
This isn't a full fix, however, because there are bound to be other fragile commands that will break my code...Christian's approach of generating the table, rather than storing it, is probably the best solution.
x=...,y=...
way necessary at all? Why not using{1,2},{3,$\overrightarrow{AB}$}
directly, splitting this?