Skip to main content

Open Office Java API

Posted by tchangu on December 30, 2005 at 6:20 AM PST

When I worked for a consulting firm I got an opportunity to work on a Strategy & Operations pursuit. The task was to fill up a 20 page MS Word report template with lots of data from MS Access and Oracle (which was backend to some ERP system). The requirement was to produce 10 or so reports quickly, which showed the client how the firm can help them to define a strategic sourcing model followed by a transformation roadmap.



Not being a fluent VB Scripter, I was totally frustrated trying different things - manually plugging in data, patchy VB Scripting, Apache POI - but nothing worked satisfactorily. Finally after looking around, I ended up discovering OpenOffice UNO Java API (Universal Network Objects). After going through an initial ramp, it worked out pretty good. With OO UNO and JDBC, ugly and complex reporting became a breeze!



Open Office UNO API is pretty involved in concept and is complex as well. Of course it’s pretty powerful and can do much more than what I made use of. However, there is very little general documentation like articles etc available online. But Sun’s Developer's guide and supplied samples is very good. For starters here is some code that helped me going.



First - Read an existing document, and this can be accomplished by


// get the remote office component context
xContext = com.sun.star.comp.helper.Bootstrap.bootstrap();
System.out.println("Connected to a running office ...");

// Get the remote office service manager
XMultiComponentFactory xMCF = xContext.getServiceManager();

// Get the root frame (i.e. desktop) of openoffice framework.
Object oDesktop = xMCF.createInstanceWithContext("com.sun.star.frame.Desktop", xContext);

// Desktop has 3 interfaces. The XComponentLoader interface provides ability to load
// components.
XComponentLoader xCompLoader = (XComponentLoader)
UnoRuntime.queryInterface(com.sun.star.frame.XComponentLoader.class, oDesktop);

// URL of the component to be loaded
String sUrl = "file:///[file name]";

// Load the document, which will be displayed. More param info in apidoc
XComponent xComp = xCompLoader.loadComponentFromURL(sUrl, "_blank", 0, new PropertyValue[0]);

// Get the textdocument
XTextDocument aTextDocument = (XTextDocument)UnoRuntime.queryInterface(
                  com.sun.star.text.XTextDocument.class, xComp);

Now that we have text document we can manipulate in how ever manner we want. In my particular case, I had to deal with data that were in tables. This was accomplished by
// Query the XTextTablesSupplier interface from our document
XTextTablesSupplier xTablesSupplier = (XTextTablesSupplier) UnoRuntime.queryInterface(
                 XTextTablesSupplier.class, aTextDocument );

// Get the tables collection
XNameAccess xNamedTables = xTablesSupplier.getTextTables();

// Query the XIndexAccess from the tables collection
XIndexAccess xIndexedTables = (XIndexAccess) UnoRuntime.queryInterface(
                 XIndexAccess.class, xNamedTables);

for (int i = 0; i < xIndexedTables.getCount(); i++) {
  Object table = xIndexedTables.getByIndex(i);
  XTextTable xTable = (XTextTable) UnoRuntime.queryInterface(
                  XTextTable.class, table);

  // Getting Table Rows
  XTableRows xRows = xTable.getRows();

  // Getting the right Table Cell (Hard Coded as B2).
   XText xCellText = (XText) UnoRuntime.queryInterface (
                  XText.class, xTable.getCellByName ( "B2" ) );

   // Make JDBC calls. Perform data tranformation and set it
   xCellText.setString("Hello Worlds");
}

The final task after all the transformation has been performed is to save the document.
// URL where the document is to be stored
String storeUrl = "file:///Test_97.rtf";

XStorable xStorable = (XStorable)UnoRuntime.queryInterface(XStorable.class, aTextDocument);
PropertyValue[] storeProps = new PropertyValue[1];
storeProps[0] = new PropertyValue();
storeProps[0].Name = "FilterName";
storeProps[0].Value = "Rich Text Format";

xStorable.storeAsURL(storeUrl, storeProps);

Of course the document could be sent to the printer as well. Here is the code to do that
XPrintable xPrintable = (XPrintable)UnoRuntime.queryInterface(XPrintable.class, aTextDocument);
PropertyValue[] printerDesc = new PropertyValue[1];
printerDesc[0] = new PropertyValue();
printerDesc[0].Name = "Name";
printerDesc[0].Value = "PDFCreator";
xPrintable.setPrinter(printerDesc);

PropertyValue[] printOpts = new PropertyValue[1];
printOpts[0] = new PropertyValue();
printOpts[0].Name = "Pages";
printOpts[0].Value = "1";
xPrintable.print(printOpts);

Enjoy!

Related Topics >>