To illustrate modifying a BIRT chart at runtime, assume we have a bar chart that we wish to add additional line series to, based on some report parameter. This can be accomplished by creating an event handler for the beforeFactory event and modifying the report prior to it running.
cht = reportContext.getDesignHandle().findElement(“MyChart”);
This line of code requires that the chart be named MyChart in the General tab of the Properties View. This line of code gets a handle to the Chart report item. Once the chart report item is located we then can retrieve the actual chart model. The chart model is de-serialized from the xml within the report design and stored in a property called chart.instance. So to get the model, you can use code like the following:
mychart = cht.getReportItem().getProperty(“chart.instance”);
Now that we have the actual chart model, we can use standard chart engine API calls to modify it prior to the report running. Remember to import the CE API packages prior to using them. See the final example for more details.
Since we have a bar chart, the chart model will be an instance of the ChartWithAxesImpl class. This class has methods for getting the chart axes and adding series definitions. If we define a static report parameter that allows multi-selection, with values that correspond to the row values we want to map with line series, the following code will add the appropriate series.
//Get the x axis
xAxis =mychart.getAxes().get(0);
//Get the first y axis
yAxis1 = xAxis.getAssociatedAxes().get(0);
alternate_label_position = false;
for( i=0; i < params["SelectSeriesToAdd"].value.length; i++){
var sdNew = SeriesDefinitionImpl.create();
var ls = LineSeriesImpl.create();
ls.getLabel().setVisible(true);
if( alternate_label_position ){
ls.setLabelPosition( Position.BELOW_LITERAL );
alternate_label_position = false;
}else{
ls.setLabelPosition( Position.ABOVE_LITERAL );
alternate_label_position = true;
}
var qry = QueryImpl.create("row[\"" + params["SelectSeriesToAdd"].value[i] + "\"]" );
ls.getDataDefinition().add(qry)
sdNew.getSeries().add( ls );
yAxis1.getSeriesDefinitions().add( sdNew );
The for-loop iterates over the selected values within the parameter and creates a Line series for each value. The value of each parameter is used as the query for the new series. Finally the new series definition is added to the first y axis.
The final code the beforeFactory event handler looks like:
importPackage(Packages.org.eclipse.birt.chart.model.data.impl);
importPackage(Packages.org.eclipse.birt.chart.model.component.impl);
importPackage(Packages.org.eclipse.birt.chart.model.type.impl);
importPackage(Packages.org.eclipse.birt.chart.model.attribute);
//Chart must be named
cht = reportContext.getDesignHandle().findElement("MyChart");
mychart = cht.getReportItem().getProperty( "chart.instance" );
//Get the x axis
xAxis =mychart.getAxes().get(0);
//Get the first y axis
yAxis1 = xAxis.getAssociatedAxes().get(0);
//alternate the series label position of each new series
alternate_label_position = false;
for( i=0; i < params["SelectSeriesToAdd"].value.length; i++){
//create a new series definition for each new series
var sdNew = SeriesDefinitionImpl.create();
//create a new series for each parameter selection
var ls = LineSeriesImpl.create();
ls.getLabel().setVisible(true);
if( alternate_label_position ){
ls.setLabelPosition( Position.BELOW_LITERAL );
alternate_label_position = false;
}else{
ls.setLabelPosition( Position.ABOVE_LITERAL );
alternate_label_position = true;
}
//Create the query. The row value must correlate with the data set row value
var qry = QueryImpl.create("row[\"" + params["SelectSeriesToAdd"].value[i] + "\"]" );
ls.getDataDefinition().add(qry)
sdNew.getSeries().add( ls );
//Add the new series definition to the first y axis
yAxis1.getSeriesDefinitions().add( sdNew );
}

The complete example is located here.
For an example of resizing a chart dynamically see
this.
Hi Jason,
ReplyDeletethank you for this interesting post, I'm in needing of something like this but with a scripted data set (instead of queries).
I tried to understand how to add data in a different manner than this:
//Create the query. The row value must correlate with the data set row value
var qry = QueryImpl.create("row[\"" + params["SelectSeriesToAdd"].value[i] + "\"]" );
ls.getDataDefinition().add(qry)
but cannot find any informations on the net about... any hint?
Thanks a lot
Fred
Fred,
ReplyDeleteIt should not matter if it is a scriped dataset or a normal query. The QueryImpl.create function is looking for a bound column name. Look at the binding tab in the property editor for the chart.
Jason
It's well and fine, but for exemple, how do you do this , if you want to apply one methode on the row values for the Y-Series like this :
ReplyDeleteQuery query = QueryImpl.create("row[\"product\"].length");
that will not work. In the Designer you will note, that the value of the Y-Series is row["product"] , but the length function is ignored...
How can you resolve that ?
Thanks,
JBill.
JBill,
ReplyDeleteDid you get this issue worked out?
Did you try adding a new bound column with its value set to
dataSetRow["PRODUCT"].length
Jason
When you export the plugin project,
ReplyDeleteplease do not use Export --> Java --> JAR file
Instead, export to this: "Deployable plug-ins and fragments."
Then it will work.
And the new library added one more arguments to the execute method:
public Object execute( Object[] args, IScriptFunctionContext arg1)
when i published a similar dynamic series in MAXIMO it gave the error "SeriesDefinitionImpl is not defined".
ReplyDeletePlease help me to solve it.
Did you do the imports?
ReplyDeleteimportPackage(Packages.org.eclipse.birt.chart.model.data.impl);
importPackage(Packages.org.eclipse.birt.chart.model.component.impl);
importPackage(Packages.org.eclipse.birt.chart.model.type.impl);
importPackage(Packages.org.eclipse.birt.chart.model.attribute);
Jason ..I added all those imports.. I guess the org.eclipse.birt.chart.engine.jar is not recognized in MAXIMO... It didnt show any error for the imports, but it said "SeriesDefinitionImpl is not defined" ... any clue about the problem ?? my beforefactory method is almost same like your example except for the looping structure...
ReplyDeleteThis comment has been removed by the author.
ReplyDeleteDo you know what BIRT version is being used?
ReplyDeleteHi Jason ,
ReplyDeleteam using birt 2.3.2 .. its IBM's birt... i googled the error text "reference error SeriesDefinitionImpl is not defined" but couldnt find anything useful... i guess no one has got this error before .. thanks for quick reply ... please help me if have got any idea about this error..
Thanks ,
Rajesh
Hi Jason,
ReplyDeleteLineSeriesImpl.create() method returns SereisImpl which is why LineChart is not getting created.
I'm using Birt 2.3
I am not 100% on what you are saying. Can you email me a report that uses the sample db that shows the issue?
ReplyDeleteJason
hi Jason,
ReplyDeleteThanks for this post very interesting,
i tried to do the same, but it doesn't work :( i got an exeption caused by :
org.mozilla.javascript.EcmaError: TypeError: Cannot call method "getReportItem" of null
How can i resolve that ?
Did you name the chart? The error you are getting indicates that you either did not name it our you used the wrong name here:
ReplyDeletecht = reportContext.getDesignHandle().findElement(“MyChart”);
i see, i corrected the probleme, now i'm getting in preview an empty image.
ReplyDeleteany idea ?
if you switch to the xml view does it show any red icons in the margin?
ReplyDeleteyes exactly, that's what it shows ...
ReplyDeleteif you mouse over the red icon what error pops up?
ReplyDeletethere is no problem in the xml, but in the preview i got an empty image with an X icon on the top.
ReplyDeletei don't know if the problem is linked to the data set or the data source ?
can you email me the report? jasonweathersby at windstream.net
ReplyDeletei sent it to jasonweathersby@windstream.net
ReplyDeleteplz tell me if u didn't get it.
Thank you.
I replied to you.
ReplyDeleteThanks for this blog. It really provides awesome information to all readers. keep it up and keep posting these types of blogs on digital marketing services, it's really helpful.
ReplyDeletefixed asset management companies
Sharma Academy is Central Indias largest provider of Mppsc Notes and Mppsc Study Material. You will get updated MPPSC Notes as per the latest syllabus of state level psc exam in Hindi and English medium both. Students can read free mppsc notes for their exam preparation
ReplyDelete