Wednesday, August 26, 2009

Using Script to Modify a BIRT Chart

When designing BIRT reports that contain charts, the developer has many ways a chart can be customized. One way is to implement a script event handler either in JavaScript or Java. The chart engine currently supports over thirty hooks for implementing an event handler. These events are fired during the generation and rendering of the chart. Many items can be customized. For example, the data for a chart can be changed in the afterDatasetFilled script, or the entire chart model can be changed in the beforeGeneration script.


In addition to changing the chart using the chart scripting hooks, the chart model can also be changed using the primary BIRT report script hooks. When making changes to the report, most developers will use the beforeFactory event script. This event is fired prior to running the report and offers a location to make simple or complex changes to the report. This includes modifying any charts that exist within the report. Simple chart properties can be changed using the Chart Simple API. An example of this approach is described here.

For more complex changes, the Chart API can be called within the script. As an example, changing a specific chart series type is possible. BIRT 2.5 provides study charts which allow multiple Y-axes to be stacked, each with a different series type. Turning this feature on or off can also be done using script. These two changes can be done with the following script:

First import the API packages that will be needed.

importPackage(Packages.org.eclipse.birt.chart.model.data.impl);
importPackage(Packages.org.eclipse.birt.chart.model.type.impl);
importPackage(Packages.org.eclipse.birt.chart.model.attribute.impl);


Retrieve the report design handle and find the chart. Note that the chart needs to be named. This can be done in the general properties for the chart.

//Chart must be named
cht = reportContext.getDesignHandle().findElement("MyChart");
//get the chart model;
mychart = cht.getReportItem().getProperty( "chart.instance" );



Next retrieve the axes. In this example the chart has two Y-Axes. The second one contains the series to be modified.

xAxis =mychart.getAxes().get(0);
yAxis2 = xAxis.getAssociatedAxes().get(1);

Clear all series definitions defined for the second Y-axis.

yAxis2.getSeriesDefinitions().clear();

The example report contains a combo parameter that allows the user to select the series type for the second Y-Axis. The parameter is checked and an appropriate series is created. Note that if an area series is created, the background is set to translucent.

if( params["SeriesType"].value == "Line"){
var ns = LineSeriesImpl.create();
}else if( params["SeriesType"].value == "Bar"){
var ns = BarSeriesImpl.create();
}else if( params["SeriesType"].value == "Area"){
var ns = AreaSeriesImpl.create();
ns.setTranslucent(true);
ns.getLineAttributes().setColor(ColorDefinitionImpl.TRANSPARENT())


}

Create a new series definition and set the appropriate query and series type.

var sdNew = SeriesDefinitionImpl.create();
sdNew.getSeriesPalette( ).shift( 0 );
ns.getLabel().setVisible(true);
var qry = QueryImpl.create("row[\"QUANTITYORDERED\"]" );
ns.getDataDefinition().add(qry)
sdNew.getSeries().add( ns );

Assign the new series definition to the second Y-Axis.

yAxis2.getSeriesDefinitions().add( sdNew );

The example report also has a Boolean parameter that determines if the chart should be displayed as a study chart.


if( params["StudyChart"].value == true ){
mychart.setStudyLayout(true);
}else{
mychart.setStudyLayout(false);
}

Some of the output options for this example report are displayed below.


This report is available at Birt-Exchange.

Thursday, August 13, 2009

Calling BIRT reports from PHP using Actuate’s JSAPI

I have written a couple of post on using Actuate’s JSAPI to include BIRT content within your system. This API is AJAX based and allows content to be embedded within most web applications.

These post can read here:
Calling BIRT Reports from ASP.NET
and
Actuate's JSAPI

In addition take a look at calling the BIRT Engine from PHP, which I blogged about a while back.

Calling the JSAPI from PHP is not much different than any other front end. For example, including the interactive viewer can be done using the following code.



<?php
$JSAPI_Location='http://localhost:8080/ActuateJavaComponent/jsapi';
$ReportFile='/Public/BIRT and BIRT Report Studio Examples/Customer Dashboard.rptdesign';
?>
<HTML>
<head>
</head>
<body>

<div id="jsapi_example_container">
<script type="text/javascript" src="<?php echo $JSAPI_Location ?>"></script>
<script type="text/javascript" language="JavaScript">
<!-- Load the viewer component of the Actuate object -->
actuate.load("viewer");
actuate.initialize("<?php echo substr($JSAPI_Location, 0, -5) ?>",
null,
null,
null,
initViewer);
var viewer;
function initViewer()
{
viewer = new actuate.Viewer("acviewer");
<!-- register an event handler to catch exceptions -->
viewer.registerEventHandler(actuate.viewer.EventConstants.ON_EXCEPTION, errorHandler);
run();
}
function run()
{

viewer.setReportName("<?php echo $ReportFile ?>");
viewer.submit();
}
function errorHandler(viewInstance, exception)
{
alert(exception.getMessage());
}
</script>
<div id="acviewer"></div>
</div>
</body>
</HTML>


In this example I am setting the JSAPI location and report file to run using a couple of PHP variables. The JSAPI is initialized and the callback function initViewer is called which creates the viewer within the acviewer div element. The initViewer function then calls the run method which sets the report to run and executes it. The report is then displayed within the acviewer div element.



If the report has parameters you can use the parameter component of the JSAPI or set them using PHP variables.

Change the code above to add the parameter values.

<?PHP
$JSAPI_Location='http://localhost:8080/ActuateJavaComponent/jsapi';
$ReportFile='/Public/BIRT and BIRT Report Studio Examples/Sales By Territory.rptdesign';
$reportTerritory='NA';
$reportYear=2004;
?>

Next, within the run method set the parameters using code similar to the following.

function run()
{
viewer.setParameters(
{
"Territory": "<?php echo $reportTerritory ?>",
"currentYear": <?php echo $reportYear ?>
}
);
viewer.setReportName("<?php echo $ReportFile ?>");
viewer.submit();
}

To use the parameter component use code similar to the following.

<html>
<body>
<?php
$JSAPI_Location='http://localhost:8080/ActuateJavaComponent/jsapi';
$ReportFile='/Public/BIRT and BIRT Report Studio Examples/DateTest.rptdesign';
?>


<div id="jsapi_example_container">
<script type="text/javascript" src="<?php echo $JSAPI_Location ?>"></script>
<script type="text/javascript" language="JavaScript">
var paramObj;
var viewer;
actuate.load("viewer");
actuate.initialize("<?php echo substr($JSAPI_Location, 0, -5) ?>",
null,
null,
null,
init);

function init()
{
<!-- parameter -->
paramObj = new actuate.Parameter("parampane");
<!-- register an event handler to catch exceptions -->
paramObj.registerEventHandler(actuate.parameter.EventConstants.ON_EXCEPTION, parameterErrorHandler);
<!-- viewer -->
viewer = new actuate.Viewer("viewerpane");
var viewerwidth = 800;
var viewerheight = 600;
<!-- register an event handler to catch exceptions -->
viewer.registerEventHandler(actuate.viewer.EventConstants.ON_EXCEPTION, errorHandler);
viewer.setWidth(viewerwidth);
viewer.setHeight(viewerheight);
runParam();
}

function runParam()
{
paramObj.setReportName("<?php echo $ReportFile ?>");
paramObj.submit(function () {document.getElementById("run").style.visibility = 'visible';});
}

function run()
{
paramObj.downloadParameterValues(runNext);
}

function runNext( pvs )
{
viewer.setParameterValues(pvs);
viewer.setReportName("<?php echo $ReportFile ?>");
viewer.submit();
}

function errorHandler(viewInstance, exception)
{
alert(exception.getMessage());
}

function parameterErrorHandler(exception)
{
alert(exception.getMessage());
}

</script>
<table border=1>
<tr>
<td><div id="parampane"></div></td>
<td><input type="button" class="btn" id="run" value="Run Report" onclick="run()" style="visibility: hidden"></td>
</tr>
</table>
<div id="viewerpane"></div>
</div>
</body>
</html>


The run function downloads the parameters that were set using the parameter component. Next the setParameterValues method is used to set the parameter values for the run of the report. Notice this example has a date parameter, and the JSAPI provides a date picker for this type of parameter.





If you are already using some PHP class to implement a date picker, such as the one available at the Zebra PHP Components Framework blog, you can modify your code to retrieve the date from the id of the element the date is stored in. The above example would have the following modifications:

<?php
// include the class
require "class.datepicker.php";
// instantiate the object
$dp=new datepicker();
$dp->dateFormat="m/d/Y";

$JSAPI_Location='http://localhost:8080/ActuateJavaComponent/jsapi';
$ReportFile='/Public/BIRT and BIRT Report Studio Examples/DateTest.rptdesign';
?>

function runNext( pvs )
{
//viewer.setParameterValues(pvs);
viewer.setParameters({"currentYear":2003, "currentMonth":12, "DateParameter":document.getElementById("date").value});

viewer.setReportName("");
viewer.submit();
}


<table border=1>
<tr>
<td><input type="text" id="date"></td>
<td><input type="button" value="Select Date" onclick="<?=$dp->show("date")?>"></td>
</tr>

<tr>
<td><div id="parampane"></div></td>
<td><input type="button" class="btn" id="run" value="Run Report" onclick="run()" style="visibility: hidden"></td>
</tr>
</table>
<div id="viewerpane"></div>