2019-08-18

24: Execute UNO Dispatch Command and Get All Information in Basic

<The previous article in this series | The table of contents of this series | The next article in this series>

In LibreOffice or Apache OpenOffice Basic. Your lazy way may be missing some useful information that is available from the execution.

Topics


About: UNO (Universal Network Objects)
About: LibreOffice
About: Apache OpenOffice
About: LibreOffice Basic
About: Apache OpenOffice Basic

The table of contents of this article


Starting Context



Target Context


  • The reader will know how to execute any UNO dispatch command and get the result information and the related information in LibreOffice or Apache OpenOffice Basic.
Stage Direction
Here are Hypothesizer 7, Objector 24A, and Objector 24B in front of a computer.


Orientation


Hypothesizer 7
In this article, we will know how to execute any UNO dispatch command and get the result information and the related information, in LibreOffice or Apache OpenOffice Basic.

Objector 24B
I know how to execute any UNO dispatch command, but I don't know how I can get what you call "related information" in your descriptions of some UNO dispatch commands; the execution doesn't return such information!

Hypothesizer 7
Ah, madam, I guess that you execute the UNO dispatch command with a 'com.sun.star.frame.DispatchHelper'.

Objector 24B
Of course. I have heard that that is the way.

Hypothesizer 7
In fact, that is a simplified way, which offers only partial information.

Objector 24B
. . . So, do I have to change the way to execute the UNO dispatch command?

Hypothesizer 7
Yes, you do.

Objector 24A
Do I really need such thing as "related information"?

Hypothesizer 7
Sir, while I cannot decide what you need, when a piece of useful information is offered by a UNO dispatch command, it is usually offered as related information.


Main Body


1: An Easy Way to Execute Any UNO Dispatch Command Without Getting the Related Information


Hypothesizer 7
First, let us know a way to execute any UNO dispatch command without getting the related information.

Although you may already know this way, some preliminary information for the next section, which is on executing any UNO dispatch command and getting the whole available information, will be known in this section.

Objector 24A
. . . So, you are insinuating that I shouldn't skip this section . . .

Hypothesizer 7
"insinuating"? Ah, an earthling maneuver. . . . In fact, what you do does not matter to me, but my fulfilling the obligation of timely offering due information does matter.

Objector 24A
Whatever . . .

Hypothesizer 7
Anyway, as any UNO dispatch command is executed on a frame, first, we have to get the frame. If we want to execute the UNO dispatch command on a document, we will have to get the frame that contains the document; otherwise, we will use the UNO desktop frame.

In order to get the frame that contains the document, first, we have to get access to the document UNO object.

Although we can get access to any non-current document UNO object, I will not delve into how to do so in this article (I will do so in a future article). Instead, in this article, we will use the current document, which can be accessed by the global built-in variable, 'ThisComponent'.

We get the frame UNO object, like this.

@LibreOffice or Apache OpenOffice Basic Source Code
	Dim l_controller As Object
	l_controller = ThisComponent.getCurrentController ()
	Dim l_frame As Object
	l_frame = l_controller.getFrame ()

Objector 24A
I know.

Hypothesizer 7
In fact, the frame is a 'com.sun.star.frame.XDispatchProvider' instance.

Objector 24A
Huh? What do you mean? Any frame is a frame, isn't it?

Hypothesizer 7
. . . Yes, it is, and it is also a UNO dispatchers provider.

Objector 24A
Ridiculous . . .; it's as though a thing is a sock and also a kitchen sponge.

Hypothesizer 7
. . . It is more like a person is a president and also a jerk.

Objector 24A
Ah, that is possible.

Hypothesizer 7
In fact, the frame implements the 'com.sun.star.frame.XDispatchProvider' UNO interface, although any interface does not appear in Basic code.

Objector 24A
. . . Whatever that means . . .

Hypothesizer 7
On the other hand, the UNO desktop frame UNO object can be access by the global built-in variable, 'StarDesktop'.

Objector 24A
Ah-ha.

Hypothesizer 7
And the frame is a 'com.sun.star.frame.XDispatchProvider' instance.

Objector 24A
Like a president is a jerk.

Hypothesizer 7
Whichever frame we have got access to, then, we get a UNO dispatch helper UNO object, like this, where 'l_unoObjectsContext' is a UNO objects context (usually, 'GetProcessServiceManager ().getPropertyValue ("DefaultContext")' is used).

@LibreOffice or Apache OpenOffice Basic Source Code
	Dim l_dispatchHelper As Object
	l_dispatchHelper = l_unoObjectsContext.getServiceManager ().createInstanceWithContext ("com.sun.star.frame.DispatchHelper", l_unoObjectsContext)

Objector 24A
Um? I have done 'GetProcessServiceManager ().createInstance ("com.sun.star.frame.DispatchHelper")'. What's the difference?

Hypothesizer 7
As far as you use the default UNO objects context, there is no difference; my above code is valid also for using any non-default UNO objects context.

Objector 24A
Hmm . . .

Hypothesizer 7
Finally, we execute the UNO dispatch command, specifying the command URL and the command arguments, like this.

@LibreOffice or Apache OpenOffice Basic Source Code
	Dim l_dispatchArgumentPropertiesArray (0) As New com.sun.star.beans.PropertyValue
	l_dispatchArgumentPropertiesArray (0).Name = "ToPoint"
	l_dispatchArgumentPropertiesArray (0).Value = "$B$2"
	Dim l_commandResult As Object
	l_commandResult = l_dispatchHelper.executeDispatch (l_frame, ".uno:GoToCell", "_self", -1, l_dispatchArgumentPropertiesArray)

Objector 24A
Actually, I have never understood what "_self" is doing there. What is the self of what?

Hypothesizer 7
Actually, the target frame is the self of the specified frame ('l_frame').

Objector 24A
Oh . . ., that seems to mean, I don't have to specify the target frame.

Hypothesizer 7
You do not have to. For example, you can specify a child frame and the '_parent' target frame name.

Objector 24A
That seems to mean, the frames form a hierarchy.

Hypothesizer 7
In fact, any frame belongs to a hierarchy of frames, and any hierarchy is under the root frame (which is the desktop).

Objector 24A
Huh? That's an odd statement; I would say, "there is a single hierarchy whose top is the desktop.".

Hypothesizer 7
However, the '_top' frame of the specified frame is not the desktop, but the frame under the desktop.

Objector 24A
Huh? Do you speak English?

Hypothesizer 7
Well, I have not defined such terms.

Objector 24A
So, is the '_parent' frame of the '_top' frame the desktop?

Hypothesizer 7
Yes.

Objector 24A
. . . What other frame names can I use?

Hypothesizer 7
You can use '_blank', which means a new top frame.

Objector 24A
Then what does "-1" mean in the above code?

Hypothesizer 7
"-1" means nothing, as when the specified target name is a special frame name like '_self', the argument (which is for specifying the target frame search flag) is ignored.

Objector 24A
Ah-ha.

Hypothesizer 7
As for any Calc document, the frame we have gotten is a top frame, which has no child.

Objector 24A
I see.


2: The Way to Execute Any UNO Dispatch Command and Get the Result Information and the Related Information


Hypothesizer 7
In order to get the related information, we have to take the way discussed in this section.

As the result information and the related information are informed to a 'com.sun.star.frame.XDispatchResultListener' and a 'com.sun.star.frame.XStatusListener', respectively, we usually create a class that that implements 'com.sun.star.frame.XDispatchResultListener' and create one or more classes that implement 'com.sun.star.frame.XStatusListener'.

But unfortunately, LibreOffice or Apache OpenOffice Basic does not allow us to create any class.

But fortunately, LibreOffice or Apache OpenOffice Basic allows us to create a listener object without our creating any listener class.

Unfortunately, the listener-objects-creating feature is quite restrictive (we cannot create any listener object that implements multiple UNO interfaces, we cannot add any member variable to the listener object, etc.), but fortunately, that does not prevent us from doing the indispensable things, although we may be forced to write non-ideal code, unfortunately.

For example, these are a 'com.sun.star.frame.XDispatchResultListener' object and a 'com.sun.star.frame.XStatusListener' object.

@LibreOffice or Apache OpenOffice Basic Source Code
Private Sub UnoDispatchingResultListener_dispatchFinished (a_dispatchResultEvent As com.sun.star.frame.DispatchResultEvent)
	MsgBox ("### The dispatch execution is finished.")
End Sub

Private Sub	UnoDispatchingResultListener_disposing (a_eventSource As com.sun.star.lang.EventObject)
End Sub

Private Sub UnoDispatchingRelatedInformationPieceListener_statusChanged (a_relatedInformationPiece As com.sun.star.frame.FeatureStateEvent)
	MsgBox ("### A dispatch execution related information piece is offered.")
End Sub

Private Sub UnoDispatchingRelatedInformationPieceListener_disposing (a_eventSource As com.sun.star.lang.EventObject)
End Sub
	
	Dim l_unoDispatchingResultListener As Object
	l_unoDispatchingResultListener = CreateUnoListener ("UnoDispatchingResultListener_", "com.sun.star.frame.XDispatchResultListener")
	Dim l_unoDispatchingRelatedInformationPieceListener As Object
	l_unoDispatchingRelatedInformationPieceListener = CreateUnoListener ("UnoDispatchingRelatedInformationPieceListener_", "com.sun.star.frame.XStatusListener")

Please look those event classes up in the UNO API document (here for 'com.sun.star.frame.DispatchResultEvent', here for 'com.sun.star.lang.EventObject', and here for 'com.sun.star.frame.FeatureStateEvent').

Objector 24A
Well, I should create the subroutiness that have the names of a prefix plus the method names of the to-be-implemented interface, and call the 'CreateUnoListener' function with the prefix and the interface name specified.

Hypothesizer 7
And of course, the argument types of each method have to coincide with those of the corresponding interface method.

Objector 24A
Of course.

Hypothesizer 7
We get the frame UNO object, in the same way explained in the previous section.

Then, we set up a 'com.sun.star.util.URL' object (a non-UNO object) like this, where 'l_unoObjectsContext' is a UNO objects context (usually, 'GetProcessServiceManager ().getPropertyValue ("DefaultContext")' is used).

@LibreOffice or Apache OpenOffice Basic Source Code
	Dim l_urlInURL As New com.sun.star.util.URL
	l_urlInURL.Complete = ".uno:GoToCell"
	Dim l_urlTransformer As Object
	l_urlTransformer = l_unoObjectsContext.getServiceManager ().createInstanceWithContext ("com.sun.star.util.URLTransformer", l_unoObjectsContext)
	l_urlTransformer.parseStrict (l_urlInURL)

Objector 24A
. . . The UNO API is a little too unkind, I can't help but notice; that much code just in order to set up a single URL . . .

Hypothesizer 7
You would want to create some utility classes.

Objector 24A
That will be a natural course of action.

Hypothesizer 7
Anyway, then, we get the dispatcher UNO object like this.

@LibreOffice or Apache OpenOffice Basic Source Code
	Dim l_dispatcher As Object
	l_dispatcher = l_frame.queryDispatch (l_urlInURL, "_self", -1)

Objector 24A
. . . Have we queried a dispatch or a "dispatcher"?

Hypothesizer 7
According to some dictionaries, 'dispatch' as a noun is an act of sending, and we have not queried any act of sending (whatever that means), but have queried something that takes care of sending, which, I believe, should be called a dispatcher.

Objector 24A
Judging from the fact that I have specified the URL in order to get the dispatcher, the dispatcher seems to be good only for the URL.

Hypothesizer 7
I would say that the dispatcher was guaranteed to be responsible only for the URL although the dispatcher might happen to be responsible also for some other URLs.

Objector 24A
Ah, so, a dispatcher may take care of some multiple URLs, but unless I know what URLs, I will be able to use the dispatcher only for the URL specified in the 'queryDispatch' call.

Hypothesizer 7
Then, we register the related information listener(s) into the dispatcher, and finally, we ask the dispatcher to dispatch our command, like this.

@LibreOffice or Apache OpenOffice Basic Source Code
	l_dispatcher.addStatusListener (l_unoDispatchingRelatedInformationPieceListener, l_urlInURL)
	Dim l_dispatchArgumentPropertiesArray (1) As New com.sun.star.beans.PropertyValue
	l_dispatchArgumentPropertiesArray (0).Name = "SynchronMode"
	l_dispatchArgumentPropertiesArray (0).Value = true
	l_dispatchArgumentPropertiesArray (1).Name = "ToPoint"
	l_dispatchArgumentPropertiesArray (1).Value = "$B$2"
	l_dispatcher.dispatchWithNotification (l_urlInURL, l_dispatchArgumentPropertiesArray, l_unoDispatchingResultListener)
	l_dispatcher.removeStatusListener (l_unoDispatchingRelatedInformationPieceListener, l_urlInURL)

If you want it asynchronous, you will not have to specify the "SynchronMode" property.

Objector 24A
Ah-ha.

Hypothesizer 7
The 'statusChanged' method can be called multiple times (or may not be called at all), and the 'dispatchFinished' method is called finally once.


3: The Conclusion and Beyond


Hypothesizer 7
Now, we know how to execute any UNO dispatch command and get the result information and the related information in LibreOffice or Apache OpenOffice Basic.

Of course, we can execute any UNO dispatch command also in some other programming languages (Java, C++, Microsoft .NET Framework (C# and Visual Basic.NET), Python, BeanShell, and JavaScript); we have learned how to do so in Java, in C++, and in C# in some previous articles, and we will learn how to do so in Python in a future article.

There are an unfinished (so far) list of UNO dispatch commands for the LibreOffice foundations and the specifications of the listed commands and an unfinished (so far) list of UNO dispatch commands for LibreOffice Calc and the specifications of the listed commands.

Although executing some UNO dispatch commands is a way to handle any LibreOffice or Apache OpenOffice instance, it does not cover all of what we can do to handle the LibreOffice or Apache OpenOffice instance: we can do more by directly handling some UNO objects (please refer to the table of contents of this series).


References


<The previous article in this series | The table of contents of this series | The next article in this series>