<The previous article in this series | The table of contents of this series |
This Series Is a Complement to the Main Series, 'To Develop UNO Extensions (LibreOffice Extensions or Apache OpenOffice Extensions)', for Applying Descriptions of the Main Series to Using UNO in Basic Macros
About: UNO (Universal Network Objects)
About: LibreOffice
About: Apache OpenOffice
About: LibreOffice Basic Programming Language
Here are -Hypothesizer and -Rebutter sitting in front of a computer screen in a room on a brook among some mountains on the Bias planet.
There is already a series, 'To Develop UNO Extensions (LibreOffice Extensions or Apache OpenOffice Extensions)', which is about developing UNO extensions that consist of Java UNO components (see here to know what UNO components are), and most of the basic ideas described there also apply to using UNO in Basic macros because they are about using UNO, which is basically language-independent specifications.
OK.
However, as some special treatment is given to the Basic mapping of UNO, we have to know them.
Why is such special treatment given to the Basic mapping of UNO?
As LibreOffice Basic lacks some functionality that is essential in UNO, that is necessary. Most conspicuously, there is no concept of interfaces in Basic.
Ah-ha.
The same with the previous scene.
As a note, as we aren't in the habit of implementing large-scale logic in Basic, we don't intend to make any exhaustive commentary on building logic using UNO in Basic.
I don't understand well.
For example, we have dealt with how to read from and write to spread sheet cells in the main series, but we won't deal with such specific logic in this series.
Ah, logic described there should be applicable to Basic; it is only a matter of which programming language the logic is written in.
So, we won't repeat the same argument just in order to show it in Basic codes.
Fine.
In fact, I don't have any incentive to write large-scale Basic codes.
Why not?
Because I can write much more extensive logic more efficiently and robustly in Java by developing UNO components: Java is more robust (doing more rigorous datum types checking), more suitable for large-scale programmings (being a full-fledged object oriented language), richer in functionality (having richer datum types such as BigDecimal, List, Set, and Map, being able to do multithreading, having richer networking functionality, being able to develop richer GUIs, and being able to access OS native features through JNI).
In fact, we aren't so familiar with Basic.
We aren't, and that's the biggest reason.
Ah-ha.
And we won't deal with details of individual UNO components, because they are or will be dealt with in the main series.
Again, they are language-independent.
In this series, we will deal with only how to invoke general UNO components in Basic.
The same with the previous scene.
A general rule about using UNO is, "Get the component context, and we can do whatever allowed us to do, using the component context."
The component context is a handle to a UNO environment, and any UNO object (see here to know what UNO objects are) as a UNO service instance (see here to know what UNO services are) receives one as the constructor argument and any external UNO program gets one, connecting to the desired UNO environment. That's what we learned in the series, 'To Develop UNO Extensions (LibreOffice Extensions or Apache OpenOffice Extensions)', and the series, 'How to Use UNO (Handle LibreOffice or Apache OpenOffice Documents) in External Java Programs'.
But . . .
. . . But what?
I wonder whether I should have said "But". . . . In fact, in Basic macros also, certainly, we can get the component context, and can handle the UNO environment using the component context.
So, what's the matter?
Nothing particularly. In fact, we can get the component context like this.
-Hypothesizer starts a LibreOffice instance, opens a Basic module, and writes a Sub in the module.
Sub testToGetDefaultComponentContext
Dim l_componentContext As Variant
l_componentContext = GetProcessServiceManager ().getPropertyValue ("DefaultContext")
End Sub
Um? Well, however we get the component context, we can use it basically the same way as we do in Java, right?
Right. . . . But . . .
. . . But what?
Well, this is a typical way of creating a UNO service instance, in Basic.
-Hypothesizer writes another Sub in the module.
Sub testToCreatServiceInstanceInTypicalWay
Dim l_globalServicesManager As Variant
Dim l_arguments (0)
Dim l_heyUnoExtensionsUnoObject As Variant
l_globalServicesManager = GetProcessServiceManager ()
l_arguments (0) = "Good morning"
l_heyUnoExtensionsUnoObject = l_globalServicesManager.createInstanceWithArguments ("thebiasplanet.uno.heyunoextensionsunoextension.HeyUnoExtensionsService", l_arguments ())
End Sub
Well, the function, 'GetProcessServiceManager', which we previously used to get the component context, actually returns the global UNO services manager (see here to know what the global UNO services manager is). . . . What is the method, 'createInstanceWithArguments'? I mean, we have used the method, 'createInstanceWithArgumentsAndContext', passing the component context, in Java.
We can use the former method also in Java, but haven't, because such a practice isn't optimal.
Why?
We have kept saying that the component context is a handle to a UNO environment, but in fact, the component context is also a container of some properties as the run time environment.
Ah-ha . . .
And the component context is something that is supposed to be passed along creation stacks of UNO objects, while the component context can be replaced with modified versions along the way.
For example, when a UNO object is created, it receives a component context; it can create a modified version of the component context (some properties can be added, some properties can be removed, some property values can be changed, or some or all of them can be done) if necessary, and passes the newest version of the component context (the modified one if modified, the received one if not modified) to another, newly created UNO object . . .
Yes. When we use 'createInstanceWithArguments', we don't pass the newest version of the component context to the newly created UNO object: a component context that the global UNO service manager recognizes as the default component context is passed to the newly created UNO object.
And that's exactly what the typical code above is doing . . .
Yes.
Well, after all, as Basic modules aren't UNO components, they don't receive particular component contexts, or we would say, they receive the default component context, and whether they explicitly pass the default component context to newly created UNO objects or not, it practically doesn't matter, because the default component context is passed either way.
That seems to be the case.
As the Basic runtime presupposes that the default component context will be always used, it doesn't directly disclose the default component context, but the global UNO service manager, and in most cases, we can do without explicitly specifying the component context to use. However, if we have to or want to explicitly specify a particular component context, we always can do so. In fact, this code works fine.
-Hypothesizer writes a Sub in the module.
Sub testToCreatServiceInstanceExplicitlySpecifyingComponentContext
Dim l_componentContext As Variant
Dim l_globalServicesManager As Variant
Dim l_arguments (0)
Dim l_heyUnoExtensionsUnoObject As Variant
l_componentContext = GetProcessServiceManager ().getPropertyValue ("DefaultContext")
l_globalServicesManager = l_componentContext.getServiceManager ()
l_arguments (0) = "Good morning"
l_heyUnoExtensionsUnoObject = l_globalServicesManager.createInstanceWithArgumentsAndContext ("thebiasplanet.uno.heyunoextensionsunoextension.HeyUnoExtensionsService", l_arguments (), l_componentContext)
End Sub
How about creating UNO service instances through 'UNO service'-specific UNO service instances factories (see here to know what we mean by ''UNO service'-specific UNO service instances factories')?
The same. We can do without passing the component context although we can pass it if we want to.
Do you mean we can just ignore the existence of the first argument that takes the component context, not pass null to the first argument?
Yes.
By the way, the component context we have talked about so far is that of the LibreOffice instance on which the Basic code runs, right?
Yes. That is the UNO environment Basic macros are usually supposed to handle.
How can we get the component context of another UNO environment, for example a UNO environment on a remote host?
I don't know how to do that by Basic self; I would be able do that through my UNO component, if necessary.
Ah, we can do that according to some descriptions of the series, 'How to Use UNO (Handle LibreOffice Documents) in External Java Programs'.
In Basic, we don't need to explicitly get any UNO proxy (see here to know what UNO proxies are) that represents each UNO interface (see here to know what UNO interfaces are): we can just call any method on an UNO object.
I remember that that is true only if the UNO component is made to support that feature (see here).
Yes, that should be the case.
We use Variant as the variable type to refer to any UNO object.
Ah, in Java, we use a UNO interface as the variable type to refer to a UNO object (to be exact, a UNO proxy).
As we can't use interfaces in Basic, we just do with using Variant.
This reference document says that we shouldn't use Object as the variable type, although Object is frequently used in examples of reference documents.
So, we should do as the reference document says, not as reference documents do . . .
We will have to know the datum types mapping between UNO and Basic.
We can look it up here.
- Apache OpenOffice Wiki. (2009/05/13). OpenOffice.org Basic. Retrieved from https://wiki.openoffice.org/wiki/Documentation/DevGuide/ProUNO/Basic/OpenOffice.org_Basic
<The previous article in this series | The table of contents of this series |