Table 89. Methods defined by the com.sun.star.text.XTextRange interface.
Return the com.sun.star.text.XText interface that contains this XTextRange.
Return a com.sun.star.text.XTextRange that references only the start position.
Return a com.sun.star.text.XTextRange that references only the end position.
Return a string that includes the text inside this text range.
Set the string for this text range, replacing existing text and clearing all styles.
A UNO interface may be derived from another. Every UNO interface is required to be derived from
A new UNO interface may be derived from another. This is not something that you do, but rather it’s
something that is done by the designer of the interface. The derived interface supports all of the methods
defined in the interface from which it is derived. For example, the com.sun.star.text.XTextCursor extends
the XTextRange interface to allow it to change the range, which makes sense if you think about what you do
with a cursor. Any object that implements the XTextCursor interface, supports the methods in Table 89 and
the new methods introduced by the XTextCursor interface.
The main points regarding interfaces (so far) are:
1) An interface defines methods. In other words, an interface defines what an object can do; including
getting and setting internal properties.
2) An interface may be derived from another interface.
3) The last portion of an interface name begins with an X.
In UNO, objects are accessed by their interface. Many of the programming languages, such as Java and C++,
force you to perform a little UNO magic and extract the correct interface before you can call the methods
defined in the interface. OOo Basic hides these details for you so that you can directly call methods and
access properties directly.
OOo Basic hides many of the complicated details, so, for most things, it is easier to write an OOo Basic
program than to write a Java script.
10.3. UNO service
A service abstractly defines an object by combining interfaces and properties to encapsulate some useful
functionality. A UNO interface defines how an object interacts with the outside world; a UNO structure
defines a collection of data; and a UNO service combines them together. Like a UNO interface, a UNO
service does not specify the implementation. It only specifies how to interact with the object.
Almost every UNO object is defined by a service, so UNO objects are called services. Strictly speaking,
however, “a service” is the object definition. The UNO object is the actual object created as defined by the
service. A service may include multiple services and interfaces. An interface usually defines a single aspect
of a service and therefore is usually smaller in scope.
Many services have a name similar to an interface name; for example, one of the interfaces exported by the
TextCursor service is the XTextCursor interface. An interface or property may be declared as optional for a
service. The XWordCursor interface is marked as optional for the TextCursor service. The implication is that
not all text cursors support the word cursor interface. In practice, you learn which text cursors support which
interfaces and then simply use them.
There are two typical methods for obtaining a service.
Get a reference to an existing object; for example, retrieving the first text table in the current
Ask a service factory to create an instance of an object; for example, if I want to insert a new text
table into a document, I ask the document to give me a new empty table, which I then configure and
insert into the document.
A service factory returns objects based on the name. The process service manager is the main object factory
for OpenOffice.org. The factory is given the service name, and the factory decides what to return. A factory
may return a brand new instance of an object, or, it may return an existing instance. Use
GetProcessServiceManager() to obtain a reference to the process service manager. Use CreateInstance to
create a service from the process service manager as shown in Listing 210.
Listing 210. Use process service manager to create a service.
Dim s As String
vManager = GetProcessServiceManager()
vFileAccess = vManager.CreateInstance("com.sun.star.ucb.SimpleFileAccess")
s = vFileAccess.getContentType("http://www.pitonyak.org/AndrewMacro.odt")
The code in Listing 210 obtains the process service manager, creates an instance of the SimpleFileAccess
service, and then uses the created service. The CreateUnoService function is a shortcut for creating a UNO
service (see Listing 211). The purpose of Listing 211 is to demonstrate the CreateUnoService function,
showing that it’s simpler than creating a service manager. Listing 211 also demonstrates some useful
functionality, using a dialog to choose a file.
Listing 211. Select a file on disk.
Function ChooseAFileName() As String
Dim vFileDialog 'FilePicker service instance
Dim vFileAccess 'SimpleFileAccess service instance
Dim iAccept as Integer 'Response to the FilePicker
Dim sInitPath as String 'Hold the initial path
'Note: The following services MUST be called in the following order
'or Basic will not remove the FileDialog Service
vFileDialog = CreateUnoService("com.sun.star.ui.dialogs.FilePicker")
vFileAccess = CreateUnoService("com.sun.star.ucb.SimpleFileAccess")
'Set the initial path here!
sInitPath = ConvertToUrl(CurDir)
If vFileAccess.Exists(sInitPath) Then
iAccept = vFileDialog.Execute() 'Run the file chooser dialog
If iAccept = 1 Then 'What was the return value?
ChooseAFileName = vFileDialog.Files(0) 'Set file name if it was not canceled
vFileDialog.Dispose() 'Dispose of the dialog
A directory can be chosen similarly.
Listing 212. Select a directory.
REM sInPath specifies the initial directory. If the initial directory
REM is not specified, then the user's default work directory is used.
REM The selected directory is returned as a URL.
Function ChooseADirectory(Optional sInPath$) As String
Dim oDialog As Object
Dim oSFA As Object
Dim s As String
oDialog = CreateUnoService("com.sun.star.ui.dialogs.FolderPicker")
'oDialog = CreateUnoService("com.sun.star.ui.dialogs.OfficeFolderPicker")
oSFA = createUnoService("com.sun.star.ucb.SimpleFileAccess")
If IsMissing(sInPath) Then
oPathSettings = CreateUnoService("com.sun.star.util.PathSettings")
ElseIf oSFA.Exists(sInPath) Then
s = "Directory '" & sInPath & "' Does not exist"
If MsgBox(s, 33, "Error") = 2 Then Exit Function
If oDialog.Execute() = 1 Then
ChooseADirectory() = oDialog.getDirectory()
The file picker and folder picker dialogs can use either the operating system supplied default dialogs, or
OOo specific dialogs. The operating system specific dialogs provide less functionality; for example, you
cannot set the initial displayed directory. Use Tools > Options > OpenOffice.org > General and place a
check next to "Use OpenOffice.org dialogs".
The code in Listing 211 creates two UNO services by using the function CreateUnoService. There are times,
however, when the service manager is required. For example, the service manager has methods to create a
service with arguments, CreateInstanceWithArguments, and to obtain a list of all supported services,
getAvailableServiceNames(). The code in Listing 213 obtains a list of the supported service names; there are
1003 services on my computer using OOo version 3.2.1; up from 562 with OOo version 1.
Listing 213. Service manager supports services.
Dim oDoc ' Document created to hold the service names.
Dim oText ' Document text object.
Dim oSD ' SortDescriptor created for the document.
Dim oCursor ' Text cursor used for sorting.
Dim i% ' Index Variable.
sServices = GetProcessServiceManager().getAvailableServiceNames()
Print "Service manager supports ";UBound(sServices);" services"
' Create a Writer document.
oDoc = StarDesktop.loadComponentFromURL( "private:factory/swriter", "_blank", 0, Array() )
oText = oDoc.getText()
' Print the service names into a Writer document.
For i = LBound( sServices ) To UBound( sServices )
oText.insertString( oText.getEnd(), sServices(i), False )
' Do not insert a blank line at the end.
oText.insertControlCharacter( oText.getEnd(), _
com.sun.star.text.ControlCharacter.PARAGRAPH_BREAK, False )
oCursor = oDoc.Text.CreateTextCursorByRange(oDoc.Text)
oSD = oCursor.createSortDescriptor()
oText.insertString( oText.getStart(), _
"Service manager supports "&UBound(sServices)&" services", False )
It is useful to look at the list of supported services. This provides insight into available functionality that you
can explore. A great example of this is shown Listing 214. An object inserted into a document must be
created by that document. Using the methods of Listing 213, you can check to see what types of objects the
document can create.
Listing 214. What objects can a document create.
REM Print the object / service types that a document can create.
REM If the document (oDoc) is missing, the current document is used.
REM If nameFilter is included, then service names that contain
REM the string are printed; based on a case insensitive compare.
REM The service names are stored in a newly created Write document.
Sub TypesDocCanCreate(Optional oDoc, Optional nameFilter$)
Dim allNames ' List of all the names.
Dim oWriteDoc ' Newly created Write document to contain the names.
Dim oText ' Document text object.
Dim s : s = "private:factory/swriter"
' Find out what this document can create.
If IsMissing(oDoc) Then
allNames = ThisComponent.getAvailableServiceNames()
allNames = oDoc.getAvailableServiceNames()
' Create a new Write document to contain the list.
oWriteDoc = StarDesktop.loadComponentFromURL(s, "_blank", 0, Array())
oText = oWriteDoc.getText()
If IsMissing(nameFilter) Then
oText.insertString ( oText.End, Join(allNames, CHR$(13)), False )
For i = LBound(allNames) To UBound(allNames)
If (InStr(allNames(i), nameFilter) > 0) Then
' Insert the text.
oText.insertString ( oText.End, allNames(i), False )
' Insert a new paragraph.
10.3.1. Setting a Read-Only Value
Some values can be set only once, so changing the value requires creating a new object. As an example,
A Calc sheet with combox controls (com.sun.star.awt.UnoControlComboBoxModel).
The controls are anchored to cells.
Each control bound to a cell.
Write a macro that finds each combobox and bind it to the cell in which it is anchored.
The obvious way to change the bound cell is to access and change the bound cell doing something like the
following code that fails because ValueBinding is read-only:
' BoundCell is a struct, so copy the value out, change it and write it back.
oBoundCell = oControlDataModel.ValueBinding.BoundCell
oBoundCell.Column = 6
oBoundCell.Row = 6
oBoundCell.Sheet = 0
oControlDataModel.ValueBinding.BoundCell = oBoundCell
If you create a new value binding object and try to set the BoundCell property, this still fails. The value
binding object must be initialized with the bound cell value, and it cannot be changed again:
Dim arg(0) as new com.sun.star.beans.NamedValue 'not a PropertyValue, a Named Value.
Dim oCellAddress As new com.sun.star.table.CellAddress
oCellAddress.Column = 6
arg(0).Name = "BoundCell"
arg(0).Value = oCellAddress
oService = oDoc.createInstanceWithArguments("com.sun.star.table.CellValueBinding", arg)
oControlDataModel.ValueBinding = oService
Using CreateInstanceWithArguments allows the service to be created and values be set when the object is
initialized. You can accomplish the same thing in two steps (instead of one) by creating the instance without
arguments and calling the initialize method after creating the object.
OpenOffice has “things” that are available by name. For example, the type description manager and the
service manager. A context is a collection of name-value pairs that you can use to get these “things” by
name. OOo maintains a default context that is available with the function GetDefaultContext. Although a
context is required when a service is created, OOo Basic automatically uses the default context when calling
CreateUnoService; yet another reason why OOo Basic is easier to use than other languages.
Listing 215. View context element names.
MsgBox Join(GetDefaultContext().getElementNames(), CHR$(10))
10.5. Inspecting Universal Network Objects
While writing an OOo Basic macro, I don’t always understand the values returned from internal OOo
functions — for example, inspecting the value returned by GetDefaultContext. I write test code to examine
the return values so that I can make appropriate decisions. I then frequently add more test code to further
inspect the returned object. The initial inspection uses routines that you probably know (see Table 90).
Table 90. Initial inspection routines.
Use this for optional arguments to see if they are missing.
You cannot inspect a null object, but you know that it is null.
You cannot inspect an empty object, but you know that it is empty.
Use array-inspection methods to learn more about the array.
Determine if this is a simple type such as a String or an Integer. If this is an
Object, it is probably a UNO structure or a UNO service.
Determine if this is a UNO structure.
The code in Listing 216 demonstrates an initial use of the functions in Table 90.
Listing 216. Inspect the TextTables object on the current document.
v = Thiscomponent.getTextTables()
Print IsObject(v) 'True
Print IsNull(v) 'False
Print IsEmpty(v) 'False
Print IsArray(v) 'False
Print IsUnoStruct(v) 'False
Print TypeName(v) 'Object
MsgBox v.dbg_methods 'This property is discussed later
If the returned object has a type name of Object and it isn’t a UNO structure, it is probably a UNO service.
Use the HasUnoInterfaces function to determine if a UNO object supports a set of interfaces. The first
argument is the object to test. The arguments following the first are a list of interface names. If all of the
listed interfaces are supported, the function returns True, otherwise it returns False. More than one interface
may be checked at the same time.
HasUnoInterfaces(obj, interface1[, interface2[, interface3[, ...]]])
To distinguish between a UNO structure, an arbitrary object, and a UNO service, first check to see if the
variable is an object. This is easily done using the TypeName function. If the TypeName contains the word
Documents you may be interested
Documents you may be interested