3

Hi following on from the following question on multi-line headers with pgfplotstable, the solution was to set each affected cell individually. I decided to throw together a command to do that but keep hitting an the error Argument of \reserved@a has an extra }. <inserted text> \par

The snippet I'm using is attached below -

\DeclareRobustCommand{\pgfplotstableeach}[4][1]{
    \foreach \col in {#1,...,#2}
        \foreach \ro in {0,...,#3}
        {\ifthenelse{\col=#2 \AND \ro=#3}{every row \ro\  column \col/.style=\{#4\}}{every row \ro\  column \col/.style=\{#4\},}}   
}

and this works fine to produce the text outside a pgfplotstabletypeset environment but fails inside one.

I've tried \newcommand and \newcommand{\protect\pgfplotstableeach}{<macro>} but neither works.

If I replace the macro with the text I want to input e.g. "every row 0 column 1/.style=..." it fails with a Missing \endcsname inserted. <to be read again> \protect. I actually thought this would be fairly straightforward but I'm completely bewildered by the error.

What am I doing wrong?

edited to include MWE below

\documentclass{article}
\usepackage{array,datatool,pgfplotstable}

    \begin{filecontents}{sample.csv}
       item,2008,2009,2010,2011
           ,Actual,Actual,Forecast,Forecast
           ,GBP,GBP,GBP,GBP
           ,('000),('000),('000),('000) rounded
       Area 1 OP, 1000000,1500000,1750000,250000
       Area 2 OP, 400000,500000, 450000,-50000
       Area 51 OP, 300000,375000,390000,15000
       No P, 1250000, 1000000, 950000, 50000
       Residuals, 800000, 80000, 90000, 10000
  \end{filecontents}

  \DeclareRobustCommand{\pgfplotstableeach}[4][1]{
       \foreach \col in {#1,...,#2}
          \foreach \ro in {0,...,#3}
           {\ifthenelse{\col=#2 \AND \ro=#3}
                       {every row \ro\  column \col/.style=\{#4\}}
                       {every row \ro\  column \col/.style=\{#4\},}}   
  }

\begin{document}

\pgfplotstableread[col sep=comma,header=false]{sample.csv}\mystuff

\pgfplotstabletypeset[fixed,
\pgfplotstableeach{4}{4}{string type}]\mystuff

\end{document}
3
  • \foreach takes the body of the loop in a {...} argument which you appear to be missing, apart from that it would be easier to understand the example if you posted a complete example from \documentclass to \end{document} showing the packages used and a test case for the construction. Oct 1, 2012 at 11:51
  • hi @DavidCarlisle, MWE added. The \foreach loop works okay outside the pgfplotstabletypeset environment. I think its described in the Tikz/PGF Manual on loops as a special case where two \foreach commands are nested. (and I was being a bit lazy..) Oct 1, 2012 at 13:52
  • oohh reading the manual: that's cheating:-) (sorry for the wrong comment in that case) Oct 1, 2012 at 13:55

1 Answer 1

3

Your example relies on illegal assumptions on how expansion works in TeX/PGF. In your particular case, it suffers from two problems:

  1. \foreach looses everything which has been set inside of it unless you explicitly declare it as global. In your case, it looses every option.

  2. You cannot execute custom macros directly inside of option lists.

A solution for (1.) would be to collect all your options into one huge (global!) list and execute it after the \foreach statements.

A solution for (2.) is to set all these options before \pgfplotstabletypeset. You could surround the complete statements with curly braces: this would delimit the effect (just as inside of \foreach).

Interestingly, the solution for (1.) is much more involved than it sounds. This is because the expansion of TeX is different from almost anything else that you might have encountered.

Here is a solution. You may want to decide if you want to learn the details of expansion control (i.e. questions like "what is \toks*?" or "what is \expandafter?") by studying http://pgfplots.sourceforge.net/TeX-programming-notes.pdf

\documentclass{article}
\usepackage{array,datatool,pgfplotstable}

    \begin{filecontents}{sample.csv}
       item,2008,2009,2010,2011
           ,Actual,Actual,Forecast,Forecast
           ,GBP,GBP,GBP,GBP
           ,('000),('000),('000),('000) rounded
       Area 1 OP, 1000000,1500000,1750000,250000
       Area 2 OP, 400000,500000, 450000,-50000
       Area 51 OP, 300000,375000,390000,15000
       No P, 1250000, 1000000, 950000, 50000
       Residuals, 800000, 80000, 90000, 10000
  \end{filecontents}

  \newcommand{\pgfplotstableeach}[4][1]{
    \xdef\ACCUM{}%
       \foreach \col in {#1,...,#2} {%
          \foreach \ro in {0,...,#3}
           {%
            \toks0=\expandafter{\ACCUM}%
            \edef\temp{every row \ro\space column \col/.style}%
            \toks1={#4}%
            \xdef\ACCUM{\the\toks0 \temp={\the\toks1},}%
           }%
         }%
    \message{setting \meaning\ACCUM^^J}%
     \expandafter\pgfplotstableset\expandafter{\ACCUM},
  }

\begin{document}

\pgfplotstableread[col sep=comma,header=false]{sample.csv}\mystuff

\pgfplotstableeach{4}{4}{string type}
\pgfplotstabletypeset[fixed,]\mystuff

\end{document}

note that the example is incomplete; it results in compilation failures (because only selected cells have string type).

5
  • Thanks @ChristianFeuersanger for the detailed answer. Also a really useful package in pgfplotstable. I didn't understand your last point about selected cells however, would you mind elaborating a little bit? Oct 1, 2012 at 21:16
  • Sorry scratch that query, I think you meant that col 0 also needed to be {string type}. A follow on question, when I compile this I get a , at the start of the row. Will an ifthenelse work to get rid of it or do I need to do something different? Oct 2, 2012 at 8:52
  • I am sorry - the comma is in the line after \expandafter\pgfplotstableset\expandafter{\ACCUM} - simply replace it by %. commas inside of option lists can never hurt. Oct 2, 2012 at 17:43
  • A final question - sorry - when I add an option every head row/.style={after row={\caption{blah blah}\tabularnewline}} I get a \Generic error ... #4 \errhelp \@err@ which I don't without the macro. Any thoughts would be very gratefully received. Oct 3, 2012 at 4:02
  • @TahnoonPasha Try to add the "debug" option to the option list. This will output the resulting tabular. Then: copy-paste this tabular environment into your normal document. This will reveal the problem (hopefully). Oct 3, 2012 at 6:19

You must log in to answer this question.

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