Language

The Free and Open Productivity Suite
Released: Apache OpenOffice 4.1.15

Automating OpenOffice.org

Introduction

The OpenOffice.org (OOo) supports Microsoft's Automation technology on different Windows platforms ( Windows 95,98, ME, 2000, NT4). It enables clients to control the office externally. Client programs can be contained within executables or scripts. In order to make use of the Automation capability, a client must be coded in a programming language that supports Automation. There are a variety of appropriate languages and development environments available, such as Visual C++, Visual Basic, Delphi, VBScript and JScript. In order to use a scripting language one needs a script controller that executes the script. Common controllers are the Internet Explorer as well as the Windows Script Host (WSH).

To give you an impression on how Automation works with OOo, here is a quick example:

'The service manager is always the starting point
'If there is no office running then an office is started up
Set objServiceManager= WScript.CreateObject("com.sun.star.ServiceManager")
'Create the Desktop
Set objDesktop= objServiceManager.createInstance("com.sun.star.frame.Desktop")
'Open a new empty writer document
Dim args()
Set objDocument= objDesktop.loadComponentFromURL("private:factory/swriter",_
                 "_blank", 0, args)
'Create a text object
Set objText= objDocument.getText
'Create a cursor object
Set objCursor= objText.createTextCursor
'Inserting some Text
objText.insertString objCursor, "The first line in the newly created text document."&_
        vbLf, false

This script opens a new writer document and inserts some text. If OOo is not already running, then an instance is started up automatically.
To run this example put the code into a file named test.vbs and run it with the Windows Script Host (WSH). That can be done by entering the command line:

   cscript test.vbs

in a command line window. Alternatively one can double click the file entry in the Explorer (if in doubt, look at the documentation at http://msdn.microsoft.com/scripting/default.htm). As you may have noticed, this examples is written in VBScript but you can also use JScript with the WSH.

Automation Objects

In order to do automating tasks by an external client one needs to know what automation objects are offered by the server. Currently the The StarOffice Programmers Tutorial provides this information.

Service Manager

As shown in the example at the beginning of this document, one creates a service manager first. The service manager is the starting point for all external automation tasks. It can be instantiated as every ordinary ActiveX control. How this is done, depends on the programming language being used. The WSH, for example, provides a function on the WScript object that performs instantiation.

Set objServiceManager= WScript.CreateObject("com.sun.star.ServiceManager")

This function can also be used in JScript when it is run by the WSH. Alternatively one can use the ActiveXObject object.

var objServiceManager= new ActiveXObject("com.sun.star.ServiceManager");

Once instantiated, the service manager allows access to different office components, for example

Set objDesktop= objServiceManager.createInstance("com.sun.star.frame.Desktop")

This is essentially the same as calling

objDesktop= createunoservice("com.sun.star.frame.Desktop")

as is done within StarBasic (see StarOffice Programmers Tutorial).

Creation of Types in untyped Languages

Languages, such as VBScript and JScript, do not provide types. That is, the declaration of variables do not require a type specifier:

//JScript 
var
variableOfFloat;
var variableOfBool;

'VBScript 
Dim
variableOfFloat
Dim variableOfBool

// C++ 
float
variableOfFloat;
bool variableOfBool;

In some rare situations you might need to have a concrete type. One can create them in two ways:

Set objServiceManager= WScript.CreateObject("com.sun.star.ServiceManager")
'Create the CoreReflection service that is later used to create structs
Set objCoreReflection= objServiceManager.createInstance(_
                       "com.sun.star.reflection.CoreReflection")
'get a type description class for float
Set classSize= objCoreReflection.forName("float")
'create the actual object
Dim aFloat
classSize.createObject aFloat

The other way goes like this:

Set objServiceManager= WScript.CreateObject("com.sun.star.ServiceManager")
Set aFloat= objServiceManager.Bridge_GetValueObject()
aFloat.Set "float", 3.14

The second approach uses a special object, which was dubbed "ValueObject", that can be obtained from any office object by calling Bridge_GetValueObject. This value must be explicitly told what type it represents, for more information about this object see the documentation about the OLE bridge.

You should try to use concrete types when a function that takes an any argument produces an error. Such an error could indicate a type mismatch.

Background Information

The interfaces of the office usually take parameters of concrete types. However, there is a type, the "any", that can contain values of different types, much as the VARIANT type. When a function expects an any then the OLE bridge does not know what exactly has to be in the any but it tries to convert the scripting parameter according to fixed rules (e.g. long to long, double to double). Let us have a look at these two functions:

void funcA( float f);
void funcB( any a);

When funcA is called in a script, then the OLE bridge receives a VARIANT argument. The bridge knows that funcA expects a float, therefore it converts the VARIANT into a float value. When funcB is called, the bridge needs to convert the value within the any. However, the available type information about the function only tells the argument type, which is an any in this case. Without type information for the contained type, the bridge converts the value into an UNO type according to build-in conversion rules.

An example:

someObj.funcB 3.14

The bridge will receive a VARIANT that contains a double (VBScript, JScript). The bridge will do a default conversion into a double and create an any which is being assigned the double. The implementation of funcB receives an argument of type any that contains a value of type double. A tolerant implementation should convert an any into the expected type. But unfortunately, this is not always case. If funcB is not tolerant and expects a float rather then a double, then it might throw an exception.

In most cases the bridge will be able to do a correct conversion. However, it will not work as shown in example above.

A possible source of errors is the XPropertySet interface with its methods setPropertyValue and getPropertyValue which are frequently used when writing automating programs.

Creation of Structs

If the OOo API requires a struct as argument then the struct has to be obtained from the office. It is not possible to declare a struct oneself. To make this more intelligible, let us assume there is an office function that takes a struct of type Size.

// the interface function, that will be called from script
void XShape::setSize( Size aSize)

and the struct is declared as follows:

// idl
struct Size
{
  long Width;
  long Height;
}

You cannot write code like this ( VBScript):

Class Size
  Dim Width
  Dim Height
End Class

'obtain object that implements XShape
...
'now set the size
call objXShape.setSize( new Size)

There are to ways to create the struct

Set objServiceManager= WScript.CreateObject("com.sun.star.ServiceManager")

'Create the CoreReflection service that is later used to create structs
Set objCoreReflection= objServiceManager.createInstance(_
                       "com.sun.star.reflection.CoreReflection")
'get a type description class for Size
Set classSize= objCoreReflection.forName( "Size" )
'create the actual object
Dim aSize
classSize.createObject aStruct
'use aSize
aSize.Width= 100
aSize.Height= 12

objXShape.setSize aSize

And this is the other way

Set objServiceManager= WScript.CreateObject("com.sun.star.ServiceManager")
Set aSize= objServiceManager.Bridge_GetStruct("Size")
'use aSize
aSize.Width= 100
aSize.Height= 12

objXShape.setSize aSize

The Bridge_GetStruct function can be called on any OOo object. The function is also available in JScript.

Out Parameter

Lots of interface functions take out or in/out - parameter. In some languages, such as Jscript and Java, those function arguments are not supported. To use those functions regardless, we specified that in/out and out parameters are passed as arrays. The example below shows how this is done in JScript.

// the function takes an out-parameter
var out= new Array();
object.functionOut(out);
var value= out[0];

// the function takes an in/out-parameter
var inout= new Array();
inout[0]=123;
object.functionInOut( inout);
var value= inout[0];

As one can tell from the examples, the value of the out-parameter is accessible at index 0 within the array. For in/out - parameters, one puts the in - value at index 0 of the array.

One can also use ValueObjects as in/out and out parameter. See the documentation about the OLE bridge for more details.

Listener Objects (Event Sinks)

Some components send events. In order to receive events, one has to implement a listener. A listener is distinguished by implementing a listener interface. To receive those events, one has to connect the event source with the listener. An event source usually offers a function, that takes the listener interface as argument. One only has to implement the listener interface and pass an instance of the listener as argument to the appropriate function. 

This does not only work with listeners. It is possible to implement all other interfaces an pass them to the office component. Currently, those interfaces can only be implemented in C++ and in JScript. 

You can find more details in the documentation about the OLE bridge.

Visual Basic specific hints

The UNO  interface functions which do not have a return value (i.e. return void), are mapped to sub routines, for example:

// definition of UNO function
void func( long val);

'VBScript call
func val
'or
call func( val)

Examples

WriterDemo.vbs

Apache Software Foundation

Copyright & License | Privacy | Contact Us | Donate | Thanks

Apache, OpenOffice, OpenOffice.org and the seagull logo are registered trademarks of The Apache Software Foundation. The Apache feather logo is a trademark of The Apache Software Foundation. Other names appearing on the site may be trademarks of their respective owners.