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 3 ).
Routine | Comment |
---|---|
IsMissing(obj) | Use this for optional arguments to see if they are missing. |
IsNull(obj) | You cannot inspect a null object, but you know that it is null. |
IsEmpty(obj) | You cannot inspect an empty object, but you know that it is empty. |
IsArray(obj) | Use array-inspection methods to learn more about the array. |
TypeName(obj) | 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. |
IsUnoStruct(obj) | Determine if this is a UNO structure. |
The code in Listing 4 demonstrates an initial use of the functions in Table 3.
Dim v 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. This may change when user-defined types are fully supported, but you won't obtain your own user -defined types from the OOo internals. 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) 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 Object, then you know it's an object of some sort . The next step is to see if the object is a UNO structure, by using the function IsUnoStruct. Finally, if the object supports an interface (any interface will do), you know it's a UNO service. Every interface is derived from com.sun.star.uno.XInterface, so it suffices to see if the object supports the XInterface interface. The code in Listing 5 uses the OOo Basic variable ThisComponent, which represents the current document.
Dim aProp As New com.sun.star.beans.PropertyValue Print IsUnoStruct(aProp) 'True Print HasUnoInterfaces(aProp, "com.sun.star.uno.XInterface") 'False Print IsUnoStruct(ThisComponent) 'False Print HasUnoInterfaces(ThisComponent, "com.sun.star.uno.XInterface") 'True
Tip | If the first argument to the function HasUnoInterfaces is not an object, a run-time error occurs. The object may be null, but it must be an object. If the argument is a variant, it must contain an object; it cannot be empty. |
Most UNO services also support the com.sun.star.lang.XServiceInfo interface, which allows you to ask the object what services it supports (see Table 4 ).
Method | Description |
---|---|
getImplementationName() | Returns a string that uniquely identifies the implementation of the service. For example, SwXTextDocument is the name of a Writer text document. |
getSupportedServiceNames() | Return a string array of services that the object supports. |
supportsService(serviceName) | Return True if the object supports the service name. |
OOo supports different types of documents, such as Writer (word processing) and Calc (spreadsheet). Each document type supports at least one service that is supported only by that document type (see Table 5 ). You can determine the type of document by checking if it supports one of these services. You can also use the method getImplementationName(), as shown in Table 4.
Document Type | Service |
---|---|
Drawing | com.sun.star.drawing.DrawDocument |
Writer | com.sun.star.text. Text Document |
Calc | com.sun.star.sheet.SpreadsheetDocument |
Math | com.sun.star.formula.FormulaProperties |
Presentation | com.sun.star.presentation.PresentationDocument |
The code in Listing 6 demonstrates how to verify that a variable references a Writer document. If the argument vDoc does not support the XServiceInfo interface, however, a run-time error occurs because the SupportsService method is not implemented. Use appropriate error handling if this is required, as shown in Listing 7 . If the argument is missing, the current document is used. If an error occurs or a recognized service is not supported, the text "unknown" is returned.
Sub DoSomethingToWriteDocument(vDoc) If NOT vDoc.supportsService("com.sun.star.text.TextDocument") Then MsgBox "A Writer document is required", 48, "Error" Exit Sub End If REM rest of the subroutine starts here End Sub
Function getDocType(Optional vDoc) As String On Error GoTo Oops If IsMissing(vDoc) Then vDoc = ThisComponent If vDoc.SupportsService("com.sun.star.sheet.SpreadsheetDocument") Then getDocType = "calc" ElseIf vDoc.SupportsService("com.sun.star.text.TextDocument") Then getDocType = "writer" ElseIf vDoc.SupportsService("com.sun.star.drawing.DrawingDocument") Then getDocType = "draw" ElseIf vDoc.SupportsService(_ "com.sun.star.presentation.PresentationDocuments") Then getDocType = "presentation" ElseIf vDoc.SupportsService("com.sun.star.formula.FormulaProperties") Then getDocType = "math" Else getDocType = "unknown" End If Oops: If Err <> 0 Then getDocType = "unknown" On Error GoTo 0 'Turn off error handling AFTER checking for an error End Function
Typically, when a service or interface is documented, you cannot see the entire picture in one place. For example, as of September 2003, information is available about the TextCursor service at http://api.openoffice.org/docs/common/ref/com/sun/star/text/TextCursor.html but you must follow many links to find out what the object can really do. All supported and optional interfaces are listed, but you must inspect each interface to know what each one does. Unfortunately, you don't know if the optional interfaces are supported without inspecting an object instance.
Most UNO services contain the properties dbg_properties, dbg_methods, and dbg_supportedInterfaces. Each of these properties is a string that contains a list of the supported properties, methods, or supported interfaces. Each string starts with text similar to "Properties of Object "ThisComponent":". The individual items are separated by the delimiter as shown in Table 6 . Sometimes there are extra spaces following the delimiter and sometimes there are extra new-line characters -CHR$(10).
Property | Delimiter | Description |
---|---|---|
dbg_properties | ";" | All properties supported by the object |
dbg _ methods | ";" | All methods supported by the object |
Dbg_supportedInterfaces | Chr$(10) | All interfaces supported by the object |
The code in Listing 8 provides an easy method to see what an object supports. Sometimes, however, too many items are displayed and portions of the dialog do not fit on the screen. To avoid this problem, the code in Listing 9 splits the list into smaller, easily managed chunks . Figure 1 is only one of the many dialogs that are displayed by the macro in Listing 9.
MsgBox vObj.dbg_properties MsgBox vObj.dbg_methods MsgBox vObj.dbg_supportedInterfaces
Sub ExampleDisplayDbgInfoStr() Dim vObj vObj = ThisComponent DisplayDbgInfoStr(vObj.dbg_properties, ";", 35, "Properties") DisplayDbgInfoStr(vObj.dbg_methods, ";", 35, "Methods") DisplayDbgInfoStr(vObj.dbg_supportedInterfaces, CHR$(10), 35, "Interfaces") End Sub Sub DisplayDbgInfoStr(sInfo$, sSep$, nChunks, sHeading$) Dim aInfo() 'Array to hold each string Dim i As Integer 'Index variable Dim j As Integer 'Junk integer variable for temporary values Dim s As String 'holds the portion that is not completed s = sInfo$ j = InStr(s, ":") 'Initial colon If j > 0 Then Mid(s, 1, j, "") 'Remove portion up to the initial colon Do aInfo() = Split(s, sSep$, nChunks) 'Split string based on delimiter. s = aInfo(UBound(aInfo())) 'Grab the last piece. Contains If InStr(s, sSep$) < 1 Then 'the rest if there were too many. s = "" 'If there were not, then clear s. Else 'If there was a delimiter then ReDim Preserve aInfo(nChunks - 2) 'change array dimension to End If 'remove the extra last piece. For i = LBound(aInfo()) To UBound(aInfo())'Look at each piece to remove aInfo(i) = Trim(aInfo(i)) 'leading and trailing spaces. j = InStr(aInfo(i), CHR$(10)) 'Some have an extra If j > 0 Then Mid(aInfo(i), j, 1, "") 'new line that should be removed. Next MsgBox Join(aInfo(), CHR$(10)), 0, sHeading$ Loop Until Len(s) = 0 End Sub
When a type is included in one of the "dbg_" properties, it is preceded by the text "Sbx", as shown in Figure 1. These names starting with Sbx correspond to the internal names used by OOo Basic.
Tip | A complete object browser is presented in Chapter 17 that demonstrates all of these concepts. |