I had the opportunity this week to dig into chart scripting a bit. I needed to create some y-axis marker lines (like the picture below shows) on a chart but didn’t know where the marker lines needed to be drawn until run-time. I also wanted to dynamically color the bars of the chart if they pass one of the marker lines.

You can add Marker Lines and Marker Ranges in the chart wizard, but it won’t take an expression for the value so I had to add some script in a chart event to push the number in at runtime.

The first thing I did was create some global variables to hold the value I needed for each marker line. In my example, I needed to get the locations of the marker lines from a dataset field. There are lots of places you could put this code below, but I put it in the onCreate() event of the table. You don’t have to display your data in a table just to get a chart so you could also set these global variables in a dataset script event if you like. I added my chart to the table header area and then bound my chart to the container data so the chart would change as the table was filtered as you’ll see at the bottom of this post. The code example below creates 3 global variables from table row data in the onCreate() event of the table.
reportContext.setPersistentGlobalVariable("min_val",this.getRowData().getColumnValue(”Minimum”));
reportContext.setPersistentGlobalVariable(”ok_val”,this.getRowData().getColumnValue(”Satisfactory”));
reportContext.setPersistentGlobalVariable(”great_val”,this.getRowData().getColumnValue(”Outstanding”));
Once you have filled the global variables with values, you can access them in your chart events. The code below adds 3 markers to the Y Axis of the chart, and sets the caption and color for each marker.
function beforeGeneration(chart, icsc)
{
importPackage(Packages.org.eclipse.birt.chart.model.component.impl);
importPackage(Packages.org.eclipse.birt.chart.model.data.impl);
importPackage(Packages.org.eclipse.birt.chart.model.attribute);
importPackage(Packages.org.eclipse.birt.chart.model.attribute.impl);var chart = icsc.getChartInstance();
var yAxis = chart.getAxes().get(0).getAssociatedAxes().get(0);var min_value = icsc.getExternalContext().getScriptable().getPersistentGlobalVariable("min_val");
var ok_value = icsc.getExternalContext().getScriptable().getPersistentGlobalVariable(”ok_val”);
var great_value = icsc.getExternalContext().getScriptable().getPersistentGlobalVariable(”great_val”);
min_ml = MarkerLineImpl.create(yAxis, NumberDataElementImpl.create(min_value));
min_ml.getLabel().getCaption().setValue(”Minimum”);
min_ml.getLineAttributes().getColor().set(255,0,0);
ok_ml = MarkerLineImpl.create(yAxis, NumberDataElementImpl.create(ok_value));
ok_ml.getLabel().getCaption().setValue(”Satisfactory”);
ok_ml.getLineAttributes().getColor().set(0,255,0);
great_ml = MarkerLineImpl.create(yAxis, NumberDataElementImpl.create(great_value));
great_ml.getLabel().getCaption().setValue(”Outstanding”);
great_ml.getLineAttributes().getColor().set(0,0,255);
}

I now had 3 marker lines on my chart but I also wanted to color the bars that pass the marker lines. For this, I found an example from this blog post that helped me figure out how to get the marker values from the axis. The code below gets the value of each marker line and then compares those values against the value of each datapoint. When a datapoint value crosses a marker line, the color of the bar is changed.
function beforeDrawDataPoint(dph, fill, icsc) {
chart = icsc.getChartInstance();
min_marker = chart.getAxes().get(0).getAssociatedAxes().get(0).getMarkerLines().get(0).getValue().getValue();ok_marker = chart.getAxes().get(0).getAssociatedAxes().get(0).getMarkerLines().get(1).getValue().getValue();great_marker = chart.getAxes().get(0).getAssociatedAxes().get(0).getMarkerLines().get(2).getValue().getValue();
if (dph.getOrthogonalValue() <= min_marker) {
fill.set(255,0,0);
} else if (dph.getOrthogonalValue() <= ok_marker) {
fill.set(0,255,0);
} else if (dph.getOrthogonalValue() <= great_marker) {
fill.set(0,0,255);
} else {
fill.set(255,255,0);
}
}

I now had the bars colored like I wanted and since I bound the chart to the table data, the chart automatically changes as the table is filtered. In the example below, I filtered the report by the month column selecting everything from 03-07 to 08-07 and the chart changes from 12 bars to 7 bars as shown below.

This report example was created with BIRT 2.2.0 and can be downloaded from: http://www.birt-exchange.com/modules/wfdownloads/singlefile.php?cid=2&lid=276