DIY Column Chart

If you think about it, the XFA grammar has all the graphics primitives you’d need to generate a basic column or bar chart.  It has lines, rectangles and text.  It has repeating elements (subforms).  Ok, so it doesn’t have a shadow effect.  And 3D bars are off the table.  But theoretically, all that stands between us and a simple chart is a bit of JavaScript.

By searching the web you can find samples of packages that render charts in browsers using various JavaScript frameworks.  So why not do the same in an XFA form?

Have a look at this sample PDF (here’s the data).  In particular, try modifying a value in the table and watch the bars update.  Try modifying a value to $200,000 so that the Y-axis needs to be re-scaled.  Cool.

To use one of these charts in your PDF form, open this sample in Designer and turn the chart subform into a fragment that you’ll be able to bring into other forms.  When you open in Designer you’ll see some instructions that get hidden at runtime.  The components within the chart can be styled and customized as required.  The aspects that need not be set at design time are: the positions of the dynamic elements (labels, tics, bar), the contents of the labels and the size of the bars.

Options

Once the chart is sized, positioned and styled as you like, then look at the calculate script on the chart  subform to set the rest of the parameters.  At the top of the script you will see variables for controlling the rest of the chart behaviour:

  • Bar colours
  • grid line control (short tics vs. lines that extend across the chart)
  • x label staggering (prevent overlapping labels)
  • define the gap size between bars
  • Set the maximum number of labels on the Y axis
  • Column stacking (on or off)
  • SOM expressions defining the data series

In all it was around 450 lines of generously commented JavaScript. 

Oh, and lest you think this was all original, I did borrow some Java code (converted to JavaScript) to help with the Y axis label generation.

Performance Considerations

The form makes use of dynamic subforms to draw the variable elements of the chart — X and Y labels and bars. Once the subforms were created, the script resizes and positions them correctly.  A more efficient way to draw the chart would be to pre-create a fixed number of labels and bars at design time — not wrapped in subforms.  Drawing the chart would simply use the pre-created objects and hide the ones not need.  The problem with this approach is that it is harder to author — the author is responsible for making sure there are enough labels and bars.  My version of the form opts for easier design and a slightly less efficient runtime.  But either way, this approach of rendering graphics won’t scale well to larger more complex implementations.