2

I try to write an environment for a simple barplot with pgfplots to reduce the needed markup. For that I use the environ package.

For some reason tikz complains about a format mistake at the provided coordinates.

MWE:

\documentclass[varwidth=true, border=2pt]{standalone}

\usepackage{pgfplots}
\usepackage{environ}

\NewEnviron{barplot}{%
     \begin{tikzpicture}
        \begin{axis}[
            symbolic x coords={A, B, C},
            xtick=data,
            ymax=40,
            ymajorgrids=true
          ]
            \addplot[ybar,fill=gray] coordinates {
                \BODY
            };
        \end{axis}
    \end{tikzpicture}
}

\begin{document}

\begin{barplot}
(A, 10)(B, 20)(C, 30)
\end{barplot}

\end{document}
  • 1
    I don't have any problems with the code. I have pgfplots v1.12 and TikZ v3.0.0. What is the complaint on your case? – percusse May 29 '15 at 9:23
  • @percusse Thanks for your reply. Indeed, my pgfplots version was v1.8. After I updated it, the code works. – Jan Trienes May 29 '15 at 9:36
3

If an older pgfplots wants to see an expanded coordinate list rather than a coordinate list in a macro, then it can be expanded with lots of \expandafter or the following way:

\documentclass[varwidth=true, border=2pt]{standalone}

\usepackage{pgfplots}
\usepackage{environ}

\NewEnviron{barplot}{%
     \begin{tikzpicture}
        \begin{axis}[
            symbolic x coords={A, B, C},
            xtick=data,
            ymax=40,
            ymajorgrids=true
          ]
            \edef\processme{%
              \noexpand\addplot[ybar,fill=gray] coordinates {
                \BODY
              };%
            }\processme
        \end{axis}
    \end{tikzpicture}% comment to remove unwanted space
}

\begin{document}

\begin{barplot}
(A, 10)(B, 20)(C, 30)
\end{barplot}

\end{document}

Result

Better variant of egreg, which does not expand the cell entries:

\documentclass[varwidth=true, border=2pt]{standalone}

\usepackage{pgfplots}
\usepackage{environ}

\NewEnviron{barplot}{%
     \def\process##1{%
       \addplot[ybar, fill=gray] coordinates {##1};
     }%
     \begin{tikzpicture}
        \begin{axis}[
            symbolic x coords={A, B, C},
            xtick=data,
            ymax=40,
            ymajorgrids=true
          ]
            \expandafter\process\expandafter{\BODY}
        \end{axis}
    \end{tikzpicture}%
}

\begin{document}

\begin{barplot}
(A, 10)(B, 20)(C, 30)
\end{barplot}

\end{document}

Instead of \BODY, package environ also offers an interface with \collect@body:

\documentclass[varwidth=true, border=2pt]{standalone}

\usepackage{pgfplots}
\usepackage{environ}

\makeatletter
\newenvironment{barplot}{%
  \collect@body\process@barplot
}{}
\def\process@barplot#1{%
     \begin{tikzpicture}
        \begin{axis}[
            symbolic x coords={A, B, C},
            xtick=data,
            ymax=40,
            ymajorgrids=true
          ]
            \addplot[ybar, fill=gray] coordinates {#1};
        \end{axis}
    \end{tikzpicture}%
}
\makeatother

\begin{document}

\begin{barplot}
(A, 10)(B, 20)(C, 30)
\end{barplot}

\end{document}

As percusse said, with pgfplots v1.12 and TikZ v3.0, the expansion tricks are not needed.

  • Shouldn't \noexpand\BODY be \BODY? Or am I missing something? – egreg May 29 '15 at 9:47
  • By the way, I'd do \def\processme##1{\addplot[ybar,fill=gray] coordinates {##1}} before \begin{tikzpicture} and \expandafter\processme\expandafter{\BODY}; where you do the \edef. – egreg May 29 '15 at 9:52
  • @egreg Yes, plain \BODY. The \noexpand was a left-over from a test. – Heiko Oberdiek May 29 '15 at 9:54
  • @egreg Yes, \process is better, because this method does not expand the cell entries. Also I have added a variant with interface \collect@body. – Heiko Oberdiek May 29 '15 at 10:26

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.