A Combined Chart Using OpenOffice.org Chart2 API

This Post describes a method to programatically combine different OpenOffice chart types in same coordinate system. This will be done using OpenOffice.org chart2 API as the old chart1 API is not flexible enough to allow combining multiple OpenOffice.org chart-types in same Graph. ( see my previous topic : OpenOffice Chart2 Not yet Ready! )

This Tutorial suppose you are already familiar with OpenOffice UNO API development in Java. If you are new to this field you can get started by taking a look to the Openoffice.org API developer guide.
From my own experience I found the Netbeans OpenOffice API plugin to be an Excellent Tool that could simplify the somewhat complicated tasks of java UNO API development. Kay Kroll from Netbeans.org has an article on Netbeans OpenOffice integration. He mentioned that we could extend OpenOffice.org’s charting capabilities by using the Netbeans OpenOffice Integration tool.

Now let’s walk through the steps to produce a combined chart using the chart2 API and the Java programming language. Again a warning about using com.sun.star.chart2 API; It is not provided for external usage yet. It is an internal API that will change further. When the API evolves your code will not work with future versions. If you nevertheless want to use the chart2 API on your own risk do the following:

1-Query your chart document for interface com.sun.star.chart2.XChartDocument

2-Call methods getFirstDiagram() and getDataProvider() on the returned Object from step one

3-Query the received diagram for interface com.sun.star.chart2.XCoordinateSystemContainer

4-Receive the first and only coordinate system from the container

5-Query the coordinate system for interface com.sun.star.chart2.XChartTypeContainer

The Java code snippet below shows the implementation for steps 1 to 5:

 public com.sun.star.chart2.XChartTypeContainer getChartTypeContainer() {
    /* let the Calc document create a data provider, set it at the chart */
    com.sun.star.chart2.data.XDataProvider oDataProv = xChartDoc.getDataProvider();
    com.sun.star.chart2.XDiagram  oDiagram  = xChartDoc.getFirstDiagram();
    // insert a coordinate system into the diagram
com.sun.star.chart2.XCoordinateSystemContainer oCoordSysCnt =(com.sun.star.chart2.XCoordinateSystemContainer) UnoRuntime.queryInterface(
                com.sun.star.chart2.XCoordinateSystemContainer.class, oDiagram);
 com.sun.star.chart2.XCoordinateSystem[] oCoordSys = oCoordSysCnt.getCoordinateSystems();
 // Query the coordinate system for interface com.sun.star.chart2.XChartTypeContainer
   xChartTypeContainer = (com.sun.star.chart2.XChartTypeContainer) UnoRuntime.queryInterface(
    com.sun.star.chart2.XChartTypeContainer.class, oCoordSys[0]);
        return xChartTypeContainer;
    }

6-create an instance of the line chart type :

public com.sun.star.chart2.XChartType getChartType(String type) throws Exception {
        Object  object    = xMCF.createInstanceWithContext(type, xContext);
        com.sun.star.chart2.XChartType chartType =(com.sun.star.chart2.XChartType)
        UnoRuntime.queryInterface(com.sun.star.chart2.XChartType.class, object);
        return chartType;
    }

7-add the line chart type to chart type container:

com.sun.star.chart2.XChartType lineChartType =chart.getChartType("com.sun.star.chart2.LineChartType");
  // add line chart type
  chart.getXChartTypeContainer().addChartType(lineChartType);

8-Query the new chart type for interface com.sun.star.chart2.XDataSeriesContainer:

com.sun.star.chart2.XDataSeriesContainer dataSeriesCnt=(com.sun.star.chart2.XDataSeriesContainer)UnoRuntime.queryInterface(com.sun.star.chart2.XDataSeriesContainer.class,lineChartType);

9-Create a new data series ( create an instance of service com.sun.star.chart2.DataSeries) and add it to the container:

public com.sun.star.chart2.XDataSeries getDataSeries() throws Exception {
Object object = xMCF.createInstanceWithContext("com.sun.star.chart2.DataSeries",xContext);
com.sun.star.chart2.XDataSeries oSeries =(com.sun.star.chart2.XDataSeries)
UnoRuntime.queryInterface(com.sun.star.chart2.XDataSeries.class, object);
return oSeries;
    }

dataSeriesCnt.addDataSeries(oSeries);

To connect data to the data series do the following:

10- Query the series for interface com.sun.star.chart2.data.XDataSink:

com.sun.star.chart2.data.XDataSink dataSink=(com.sun.star.chart2.data.XDataSink)UnoRuntime.queryInterface(com.sun.star.chart2.data.XDataSink.class,oSeries);

11- Use method createDataSequenceByRangeRepresentation() at the formerly received data provider to create a data sequences from the cell ranges of your choice:

com.sun.star.chart2.data.XDataSequence oSequence=oDataProv.createDataSequenceByRangeRepresentation("$Sheet1.$A$70:$C$777");

12-Set the property ‘Role’ at the data sequence to ‘values-y’:

XPropertySet cProp = (XPropertySet) UnoRuntime.queryInterface(XPropertySet.class, oSequence);
cProp.setPropertyValue("Role", "values-y");

13-Create an instance of UNO service ‘com.sun.star.chart2.LabeledDataSequence’ and use method setValues() to attach the formerly created sequence:

Object object =xMCF.createInstanceWithContext("com.sun.star.chart2.data.LabeledDataSequence", xContext);
com.sun.star.chart2.data.XLabeledDataSequence oLabeledSequence=(com.sun.star.chart2.data.XLabeledDataSequence)UnoRuntime.queryInterface(com.sun.star.chart2.data.XLabeledDataSequence.class, object);
 oLabeledSequence.setValues(oSequence);

14-Use method ‘setData()’ at the formerly received interface XDataSink to attach the labeled data sequences to the series:

com.sun.star.chart2.data.XLabeledDataSequence[] aLabeledSequence={ dLabeledSequence,oLabeledSequence,hLabeledSequence, lLabeledSequence, cLabeledSequence };
 dataSink.setData(aLabeledSequence);

Using the Netbeans OpenOffice.org plugin i created a OpenOffice Addon that implements the above 14 steps to draw a combined candle chart and 2 line charts super-imposed in the same Graph coordinate system.
the results are shown in Image below :

combined candle and line charts

(Graph programatically drawn using openoffice.org chart2 API)

As you can see this method gives quit satisfactory results. However, No doubt the Openoffice Charting component is not yet mature and is by no way a robust charting API for Java developers. SUN OpenOffice.org charting developer team admit these facts and say there is still lot of ongoing work.

Waiting for the official OpenOffice Chart2 API release , i Hope this Tutorial could be useful for some Java UNO API developers willing to start playing with the unofficial OpenOffice chart2 API.

You can check the source code demo of this project at Github.


Resources:

OpenOffice Chart2 API Not Yet Ready !

I always thought OpenOffice.org is a pretty good piece of software but I just feel that SUN has taken the wrong approach with their OpenOffice.org development. Their effort on Netbeans is miles better.

As I was working on an OOo chart extension project, I was disappointed by SUN reluctance on the com:sun:star:chart2 API. OOo chart component experts said that it is not official and they may want to change something later. However, I feel that SUN should get their act together. They have been playing with the com:sun:star:chart2 API for more than 3 years and it is still not ready. This is very sloppy for an active open source project Like OpenOffice.org !

I do not agree with SUN approach regarding the development of com:sun:star:chart2 API. Consider that you are building a car, you need to do a lot of road test to ensure that the car would behave properly. SUN is building a car behind close door, it is never a good idea. Surely, there will be changes in the course of the chart2 development, but I do not think that it would matter too much if it is done properly. After more than 3 years of development and chart2 is still not ready for use is very poor performance for a open source project.

A standard OHLC chart could be drawn on OOo perfectly. OOo could draw the OHLC chart but could not combine it with other line charts in the same graph .

What I needed is a way to modify the OpenOffice.org code so that it could superimpose charts with same coordinate system to appear on the same graph. The com:sun:star:chart API is very rigid on the chart type so I needed to develop new chart type to take care of these needs and it is not flexible to use this approach.The com:sum:star:chart2 API appears to be the answer as it has the infrastructure in place to allow you to draw more than one chart-type on the same graph under the same coordinate system.

It is obvious that SUN knows about the problem on chart1 therefore they have developed chart2. However, for some strange reason, they could not release it. Probably due to some bugs in the system and it appears that only a handful of people have participated in the development.

In my next column I will describe an algorithm that uses com:sun:star:chart2 API to combine a candle chart and line chart in same graph.

Additional Resources :

Openoffice.org Wiki Chart2