Flylib.com

Books Software

 
 
 

A Few Considerations with UNO Variables


A Few Considerations with UNO Variables

Use the EqualUnoObjects function to determine if two UNO objects are the same object. UNO structures are copied by value but UNO services are copied by reference. This means that EqualUnoObjects should always return False for two variables that contain a structure, and it might return True for UNO services.

Dim vObj
  vObj = ThisComponent
  Print EqualUnoObjects(vObj, ThisComponent)         'True

  Dim aProp As New com.sun.star.beans.PropertyValue
  vObj = aProp
  Print EqualUnoObjects(vObj, aProp)                 'False

It is almost always safe to use Object variables to hold UNO services. It is so safe, apparently, that even the macro recorder uses Object variables to hold UNO services. Unfortunately, it is not always safe. The OOo Developer's Guide specifically states that Variant variables should be used instead of Object variables. Always use the type Variant to declare variables for UNO services, not the type Object. The OOo Basic type Object is tailored for pure OOo Basic objects-in other words, objects that can be created with the Dim As New syntax. The Variant variables are best for UNO services to avoid problems that can result from the OOo Basic specific behavior of the type Object. I asked Andreas Bregas (one of the primary developers for Sun on the OOo Basic infrastructure) about this, and he said that in most cases, both work. The OOo Developer's Guide prefers Variant because there are some odd situations in which the usage of type Object leads to an error due to the old Basic Object type semantics. But if a Basic program uses type Object, it will almost always run correctly and there should be no problems.



Built-In Global UNO Variables

OOo Basic contains built-in global variables that provide quick access to frequently used components in OOo. The most commonly used variable is ThisComponent, which refers to the currently active document. To demonstrate using the variable ThisComponent, the macro in Listing 10 displays all of the styles in the current document. Figure 2 is only one of the many dialogs that are displayed while the macro runs.


Figure 2: Eight character styles used in the current document.

Listing 10: DisplayAllStyles is found in the UNO module in this chapter's source code files as SC09.sxw.

start example
Sub DisplayAllStyles
  Dim vFamilies As Variant 'All the style types
  Dim vFamNames As Variant 'Array with names of the style types
  Dim vStyles As Variant   'One style type such as Number or Page Styles
  Dim vStlNames As Variant 'Array with names of specific styles
  Dim s As String          'Message to display
  Dim n As Integer         'Iterate through the style types
  Dim i As Integer         'Iterate through the styles

  vFamilies = ThisComponent.StyleFamilies           'Get the styles
  vFamNames = vFamilies.getElementNames()           'What type of styles?
  For n = LBound(vFamNames) To UBound(vFamNames)    'Look at all style types
    s = ""
    vStyles = vFamilies.getByName(vFamNames(n))     'Get styles of a type
    vStlNames = vStyles.getElementNames()           'names of styles for type
    For i = LBound(vStlNames) To UBound (vStlNames) 'for all styles of a type
      s=s & i & "

:

" & vStlNames(i) & Chr$(13)     'Build a display string
      If ((i + 1) Mod 35 = 0) Then                  'Display 35 at a time
        MsgBox s,


,vFamNames(n)                     'Display them
        s = ""                                      'Clear string, start over
      End If
    Next i                                          'Next style
    If Len(s) > 0 Then MsgBox s,


,vFamNames(n)      'Leftover styles for type
  Next n                                            'Next style type
End Sub
end example
 

OpenOffice is based on the same code as StarOffice, which had a desktop. All of the individual windows were contained in this desktop. The desktop paradigm is now gone, but for legacy reasons a desktop object still acts as the global application that ties all of the documents together. Although I frequently see code that creates a desktop service by using the function CreateUnoService, this is not required in OOo Basic. OOo Basic provides the variable StarDesktop, which accesses the primary desktop service in OOo. The macro in Listing 11 demonstrates the use of the StarDesktop by traversing all of the currently open documents. See the results in Figure 3 .

click to expand
Figure 3: All the currently open documents.

Listing 11: Iterate ThroughAllDocs is found in the UNO module in this chapter's source code files as SC09.sxw.

start example
Sub IterateThroughAllDocs
  On Error Resume Next      'Ignore the non-document components
  Dim vComponents As Object 'All of the components
  Dim vDocs As Object       'Enumeration of the documents
  Dim vDoc As Object        'A single document
  Dim s As String
  GlobalScope.BasicLibraries.LoadLibrary("Tools")'Contains FileNameOutOfPath
  vComponents = StarDesktop.getComponents()      'Get all the components
  vDocs = vComponents.createEnumeration()        'Enumerate them
  Do While vDocs.

hasMoreElements

()               'While there are more
    vDoc = vDocs.nextElement()                   'Get the next component
    s = s & getDocType(vDoc) & "   "             'Add the document type
    s = s &

FileNameOutOfPath

(vDoc.getURL())     'Add the file name
    s = s & CHR$(10)                             'Add a new line
  Loop
  MsgBox s, 0, "Currently Open Components"
End Sub
end example
 

Tip  

The primary visible windows in OOo are called "components." Every open document is a component, as is the Basic IDE and the Help window. In OOo, the word "component" almost always means an open document.

{% if main.adsdop %}{% include 'adsenceinline.tpl' %}{% endif %}

While iterating through the open documents (components), you may find some unexpected documents. These are component windows such as the Basic IDE and the Help window. The macro in Listing 11 uses the function FileNameOutOfPath. This is another macro and is not a function that is built into OOo Basic. This function is stored in the Strings module of the application-level Tools library. If a library is not currently loaded, you cannot call the methods that it contains.

The GlobalScope variable references the application-level libraries and is used to load the Tools library. Loading a library loads all of the modules in the specified library. OOo contains libraries and modules that are not built into OOo Basic. Use the LoadLibrary method before you use the routines in the libraries.

GlobalScope.BasicLibraries.LoadLibrary("Tools")

To access the Basic libraries in the current document, either use the BasicLibraries global variable or access the BasicLibraries property in the current document.

Print EqualUnoObjects(vObj.BasicLibraries, BasicLibraries) 'True

Use the DialogLibraries variable to access the dialog libraries in the current document. Unlike BasicLibraries, an individual document does not contain a property called DialogLibaries to directly obtain the dialog libraries for a specific document. You can easily obtain the dialog and Basic libraries for a specific document through a less direct route. Each document has a LibraryContainer property.

ThisComponent.LibraryContainer.getByName("OOMECH09").getModuleContainer()
ThisComponent.LibraryContainer.getByName("OOMECH09").getDialogContainer()

The getByName() method on the LibraryContainer returns the named library. The getModuleContainer() method returns the Basic container for the specified library, and the getDialogContainer() method returns the Dialog container for the specified library. The code in Listing 12 , however, uses the variables DialogLibraries and BasicLibraries to list the number of dialogs and modules in each library in the current document. Figure 4 shows the results.


Figure 4: Dialog and Basic libraries in the current document.

Listing 12: ExamineDocumentLibraries is found in the UNO module in this chapter's source code files as SC09.sxw.

start example
Sub ExamineDocumentLibraries
  Dim vLibs           'Hold the library names
  Dim vMod            'Hold the modules/dialogs object
  Dim nNumMods%       'Number of modules or dialogs in a library
  Dim i%              'Scrap index variable
  Dim s$              'Scrap string variable
  s = "*** Dialog Libs In Document" & CHR$(10)         'Initialize s
  vLibs = DialogLibraries.getElementNames()            'Library names
  For i = LBound(vLibs) To UBound(vLibs)               'Look at each name
    vMod = DialogLibraries.getByName(vLibs(i))         'Get the dialog library
    nNumMods = UBound(vMod.getElementNames()) + 1      'How many dialogs
    s = s & vLibs(i) & " has " & nNumMods & " dialogs" 'Build string
    s = s & CHR$(10)
  Next i
  s = s & CHR$(10)
  s = s & "*** Basic Libs In Document" & CHR$(10)      'Ready for code libs
  vLibs = BasicLibraries.getElementNames()             'Library names
  For i = LBound(vLibs) To UBound(vLibs)               'Look at each name
    vMod = BasicLibraries.getByName(vLibs(i))          'Get the code library
    nNumMods = UBound(vMod.getElementNames()) + 1      'Number of modules
    s = s & vLibs(i) & " has " & nNumMods & " modules" 'Build the string
    s = s & CHR$(10)
  Next i
  MsgBox s, 0, "Libraries"
End Sub
end example
 

To view the libraries in the application-level library container, modify the code in Listing 12. Add GlobalScope before each occurrence of BasicLibraries and DialogLibraries. This change has already been made in the ExamineGlobalLibraries routine in the UNO module in this chapter's source code files.