How would I call a Java function from within OpenOffice?

Java, C++, C#, Delphi, ??? - Using the UNO bridges

How would I call a Java function from within OpenOffice?

Postby Will Pittenger » Fri Jun 15, 2012 12:39 pm

Because OpenOffice.org BASIC seems so primitive, I was thinking of coding in Java or C#. I am much more familiar with both languages. But I don't know how to trigger my code from withing OpenOffice. I assume I can assign a button to call my Java function, but don't know how.
Will Pittenger
I currently use OpenOffice 4.0 32-bit on Windows 7 64-bit (as of August 7th, 2013)
Will Pittenger
 
Posts: 45
Joined: Tue Dec 14, 2010 10:43 am
Location: Morton, IL

Re: How would I call a Java function from within OpenOffice

Postby Charlie Young » Fri Jun 15, 2012 3:00 pm

Will Pittenger wrote:Because OpenOffice.org BASIC seems so primitive, I was thinking of coding in Java or C#. I am much more familiar with both languages. But I don't know how to trigger my code from withing OpenOffice. I assume I can assign a button to call my Java function, but don't know how.


This is a big topic, about which I have much to learn myself.

If you want to add spreadsheet functions, that is an add-in. The hardest part of that using c++, and I assume Java or c#, is getting an extension shell set up. After that, you can pretty much adapt it to the desired task, though you have to learn how to deal with idl files and registries. It should also be noted that much of the online documentation on this is out of date - for example it is no longer necessary to implement AddIn, though the information about function arguments and return types is still relevant. The XAddin interface is superseded by including a CalcAddin.xcu file. Implementing XAddin still works, last I checked, but doing without it saves a big chunk of code.

If you want the sort of thing that is a called from the menus or a toolbar button, that is called an add-on, and my knowledge of that is sketchy.

You can also write routines, then call them from say, Basic, Python, or Javascript, and this is sometimes nice, especially to get something that runs faster than interpreted code. Sometimes here you need to have Office running in listening mode.

Like I say, this is a big topic.

In any case, you will need the SDK:

http://www.openoffice.org/download/sdk/index.html
Apache OpenOffice 4.1.1
Windows XP
User avatar
Charlie Young
Volunteer
 
Posts: 1559
Joined: Fri May 14, 2010 1:07 am

Re: How would I call a Java function from within OpenOffice?

Postby Villeroy » Fri Jun 15, 2012 4:51 pm

1) Macros are scripts callable from "inside the office suite" via Tools>Macros>...,from any of the script events for documents, buttons and many other objects. StarBasic knows this mode only.
Java macros are possible: [Java] OOo Writer and Calc macro examples by Hol.sten
There is always some script-URL behind such calls. The vnd.sun.star.script: protocol is handled by the office suite.
2) External programs may connect to a running office instance and access UNO components "from outside" just like they access the API of the operating system, the window manager, a database or whatever.
3) Extensions expand the office suite by adding new UNO components. These components are accessible from macros and external programs just like any other UNO component. Since StarBasic can not provide any new objects, therefore we can not write true Basic extensions. When someone publishes a Basic extension, it is just a bundle of macros (point 1 above).
"Add-in" is the term which is used for extensions that consist of integrated Calc functions with localized names, descriptions, help files, integrated in the function wizard (Ctrl+F2).
There is an additional built-in mechanism to call Basic functions from spreadsheet cells similarly to add-in functions. This has nothing to do with extensions. It's just another way to call a macro.
Please, edit this topic's initial post and add "[Solved]" to the subject line if your problem has been solved.
Ubuntu 18.04, no OpenOffice, LibreOffice 6.4
User avatar
Villeroy
Volunteer
 
Posts: 28536
Joined: Mon Oct 08, 2007 1:35 am
Location: Germany

Re: How would I call a Java function from within OpenOffice

Postby Will Pittenger » Sat Jun 16, 2012 2:00 am

Charlie Young wrote:
Will Pittenger wrote:Because OpenOffice.org BASIC seems so primitive, I was thinking of coding in Java or C#. I am much more familiar with both languages. But I don't know how to trigger my code from withing OpenOffice. I assume I can assign a button to call my Java function, but don't know how.
If you want to add spreadsheet function...

No, I'm I working on a Writer doc.

Charlie Young wrote:If you want the sort of thing that is a called from the menus or a toolbar button, that is called an add-on, and my knowledge of that is sketchy.

A button would be handy, but I just want a way to trigger the code's execution.

Charlie Young wrote:You can also write routines, then call them from say, Basic, Python, or Javascript, and this is sometimes nice, especially to get something that runs faster than interpreted code. Sometimes here you need to have Office running in listening mode.

This is what I have in mind, although I don't know what you mean by listening mode.
Will Pittenger
I currently use OpenOffice 4.0 32-bit on Windows 7 64-bit (as of August 7th, 2013)
Will Pittenger
 
Posts: 45
Joined: Tue Dec 14, 2010 10:43 am
Location: Morton, IL

Re: How would I call a Java function from within OpenOffice?

Postby Will Pittenger » Sat Jun 16, 2012 2:02 am

Villeroy wrote:1) Macros are scripts callable from "inside the office suite" via Tools>Macros>...,from any of the script events for documents, buttons and many other objects. StarBasic knows this mode only.
Java macros are possible: [Java] OOo Writer and Calc macro examples by Hol.sten
There is always some script-URL behind such calls. The vnd.sun.star.script: protocol is handled by the office suite.

Is that link demonstrating how to call a Java function from Basic? Or vice versa?
Will Pittenger
I currently use OpenOffice 4.0 32-bit on Windows 7 64-bit (as of August 7th, 2013)
Will Pittenger
 
Posts: 45
Joined: Tue Dec 14, 2010 10:43 am
Location: Morton, IL

Re: How would I call a Java function from within OpenOffice

Postby Charlie Young » Sun Jun 17, 2012 3:50 am

Will Pittenger wrote:No, I'm I working on a Writer doc.


I'll use that in my example.

Will Pittenger wrote:
Charlie Young wrote:If you want the sort of thing that is a called from the menus or a toolbar button, that is called an add-on, and my knowledge of that is sketchy.

A button would be handy, but I just want a way to trigger the code's execution.


What I'm going to suggest should work from a button.

Will Pittenger wrote:
Charlie Young wrote:You can also write routines, then call them from say, Basic, Python, or Javascript, and this is sometimes nice, especially to get something that runs faster than interpreted code. Sometimes here you need to have Office running in listening mode.

This is what I have in mind, although I don't know what you mean by listening mode.


Listening mode refers to having an Office process running in the background which enables communication with an external program. It is necessary if the program needs to directly manipulate the UNO objects in the document. It is started from the command line with either

Code: Select all   Expand viewCollapse view
soffice -invisible -accept=pipe,name=mypipe;urp;StarOffice.ServiceManager


or

Code: Select all   Expand viewCollapse view
soffice -invisible -accept=socket,host=localhost,port=2083;urp;StarOffice.ServiceManager


The pipe method is usually the one used on a local machine, and as I will discuss, can be automatically done by a program.

I needed some example of something to do with a Writer document, so I went back to this silly thing of mine, which just colors all the words in a document in a cycle.

I translated that into javascript to see how it would work that way.

Code: Select all   Expand viewCollapse view
// Color words

importClass(Packages.com.sun.star.uno.UnoRuntime);
importClass(Packages.com.sun.star.text.XTextDocument);
importClass(Packages.com.sun.star.text.XText);
importClass(Packages.com.sun.star.text.XTextCursor);
importClass(Packages.com.sun.star.text.XWordCursor);
importClass(Packages.com.sun.star.frame.XModel);
importClass(Packages.com.sun.star.beans.XPropertySet);
importClass(java.awt.Color);

WordColor = new Array();
WordColor[0] = Color(1,0,0);            //red
WordColor[1] = Color(1,165/255,0);         //orange
WordColor[2] = Color(1,1,0);            //yellow
WordColor[3] = Color(0,1,0);            //green
WordColor[4] = Color(0,0,1);            //blue
WordColor[5] = Color(75/255,0,130/255);         //indigo
WordColor[6] = Color(223/255,130/255,238/255);      //violet
n = WordColor.length;

oDoc = UnoRuntime.queryInterface(XModel,XSCRIPTCONTEXT.getInvocationContext());
if ( !oDoc )
   oDoc = XSCRIPTCONTEXT.getDocument();

xTextDoc = UnoRuntime.queryInterface(XTextDocument,oDoc);
xText = xTextDoc.getText();
nCursor = xText.createTextCursor();
wCursor = UnoRuntime.queryInterface(XWordCursor, nCursor);

nCursor.gotoStart(false);

MoreText = true;
c = 0;
while(MoreText)
{
   wCursor.gotoEndOfWord(true);
   colorer = UnoRuntime.queryInterface(XPropertySet, nCursor);
   w = WordColor[c].getRGB();
   colorer.setPropertyValue("CharColor",new java.lang.Integer(w));
   c = (c + 1) % n;
   MoreText = wCursor.gotoNextWord(false);
}


Next, I wrote a c++ program to do the coloring, the point being that one can then call the .exe file from a macro. The program, whatever language it is in, has to establish a pipe or socket connection. In older Office versions it was necessary to start the listening process as discussed earlier, then have a special routine in the program to fetch the process. Nowadays the bootstrap for the ServiceManager automatically gets a pipe connection.

In c++, that looks like this:

Code: Select all   Expand viewCollapse view
   
   // Creates a simple registry service instance.
    Reference< XSimpleRegistry > xSimpleRegistry(
        ::cppu::createSimpleRegistry() );
   
       // Connects the registry to a persistent data source represented by a URL.
    xSimpleRegistry->open( OUString::createFromAscii("C:\\Documents and Settings\\Charlie\\My Documents\\Visual Studio 2010\\Projects\\ColorWords\\ColorWords.rdb"), sal_True, sal_False );
      
    Reference< XComponentContext > xComponentContext(::cppu::bootstrap_InitialComponentContext( xSimpleRegistry ) );
   
   Reference<XComponentContext> rComponentContext = ::cppu::bootstrap ();
   Reference<XMultiComponentFactory> xServiceManager = rComponentContext->getServiceManager ();
   Reference< XMultiServiceFactory > rOfficeServiceManager (xServiceManager,UNO_QUERY);



The SDK includes Java examples illustrating the same process.

Having gotten the ServiceManager above, we can use it to get the Desktop's CurrentComponent, which here we assume is going to be a text document:

Code: Select all   Expand viewCollapse view

        Reference < XInterface  > Desktop = rOfficeServiceManager->createInstance(OUString::createFromAscii( "com.sun.star.frame.Desktop" ));
      Reference< XDesktop > xDesktop(Desktop, UNO_QUERY);
      Reference< XComponent > xcomponent = xDesktop->getCurrentComponent();
      Reference< XTextDocument > xTextDoc (xcomponent, UNO_QUERY);
      Reference< XText > oText = xTextDoc->getText();
      


It should be similar in Java, and then you can use the xTextDoc to do whatever you want (like color the words).

Once you have the .exe, written in whatever language, you can call it from a javascript macro like so:

Code: Select all   Expand viewCollapse view

importClass(Packages.com.sun.star.uno.UnoRuntime);
importClass(Packages.com.sun.star.system.XSystemShellExecute);

xCompCont = XSCRIPTCONTEXT.getComponentContext();
xMultiComponentFactory = xCompCont.getServiceManager();

shell = xMultiComponentFactory.createInstanceWithContext('com.sun.star.system.SystemShellExecute', xCompCont);
xshell = UnoRuntime.queryInterface(XSystemShellExecute, shell);

xshell.execute("C:\\...path...\\ColorWords.exe","",0);



If you do this in a jscript macro, you can attach that macro to a button or a menu item as easily as you could a Basic macro. There is no need to call Java from basic, though that is possible.
Last edited by Charlie Young on Sun Jun 17, 2012 5:28 pm, edited 1 time in total.
Apache OpenOffice 4.1.1
Windows XP
User avatar
Charlie Young
Volunteer
 
Posts: 1559
Joined: Fri May 14, 2010 1:07 am

Re: How would I call a Java function from within OpenOffice?

Postby Villeroy » Sun Jun 17, 2012 11:21 am

This is a valid hyperlink-URL from hol.sten's tutorial on Java macros:
vnd.sun.star.script:mylib.HelloWorld.printHelloWorld?language=Java&location=user
Copy the Java macro to your user profile, insert the hyperlink in a Writer document and see.
You can also draw a button with Action="Open document or web-site" and URL= the above URL
Please, edit this topic's initial post and add "[Solved]" to the subject line if your problem has been solved.
Ubuntu 18.04, no OpenOffice, LibreOffice 6.4
User avatar
Villeroy
Volunteer
 
Posts: 28536
Joined: Mon Oct 08, 2007 1:35 am
Location: Germany

Re: How would I call a Java function from within OpenOffice

Postby Will Pittenger » Sun Jun 17, 2012 10:10 pm

Charlie Young wrote:
Will Pittenger wrote:No, I'm I working on a Writer doc.


I'll use that in my example.

Will Pittenger wrote:
Charlie Young wrote:If you want the sort of thing that is a called from the menus or a toolbar button, that is called an add-on, and my knowledge of that is sketchy.

A button would be handy, but I just want a way to trigger the code's execution.


What I'm going to suggest should work from a button.

Will Pittenger wrote:
Charlie Young wrote:You can also write routines, then call them from say, Basic, Python, or Javascript, and this is sometimes nice, especially to get something that runs faster than interpreted code. Sometimes here you need to have Office running in listening mode.

This is what I have in mind, although I don't know what you mean by listening mode.


Listening mode refers to having an Office process running in the background which enables communication with an external program. It is necessary if the program needs to directly manipulate the UNO objects in the document. It is started from the command line with either

Code: Select all   Expand viewCollapse view
soffice -invisible -accept=pipe,name=mypipe;urp;StarOffice.ServiceManager


or

Code: Select all   Expand viewCollapse view
soffice -invisible -accept=socket,host=localhost,port=2083;urp;StarOffice.ServiceManager


The pipe method is usually the one used on a local machine, and as I will discuss, can be automatically done by a program.

I needed some example of something to do with a Writer document, so I went back to this silly thing of mine, which just colors all the words in a document in a cycle.

I translated that into javascript to see how it would work that way.

Code: Select all   Expand viewCollapse view
// Color words

importClass(Packages.com.sun.star.uno.UnoRuntime);
importClass(Packages.com.sun.star.text.XTextDocument);
importClass(Packages.com.sun.star.text.XText);
importClass(Packages.com.sun.star.text.XTextCursor);
importClass(Packages.com.sun.star.text.XWordCursor);
importClass(Packages.com.sun.star.frame.XModel);
importClass(Packages.com.sun.star.beans.XPropertySet);
importClass(java.awt.Color);

WordColor = new Array();
WordColor[0] = Color(1,0,0);            //red
WordColor[1] = Color(1,165/255,0);         //orange
WordColor[2] = Color(1,1,0);            //yellow
WordColor[3] = Color(0,1,0);            //green
WordColor[4] = Color(0,0,1);            //blue
WordColor[5] = Color(75/255,0,130/255);         //indigo
WordColor[6] = Color(223/255,130/255,238/255);      //violet
n = WordColor.length;

oDoc = UnoRuntime.queryInterface(XModel,XSCRIPTCONTEXT.getInvocationContext());
if ( !oDoc )
   oDoc = XSCRIPTCONTEXT.getDocument();

xTextDoc = UnoRuntime.queryInterface(XTextDocument,oDoc);
xText = xTextDoc.getText();
nCursor = xText.createTextCursor();
wCursor = UnoRuntime.queryInterface(XWordCursor, nCursor);

nCursor.gotoStart(false);

MoreText = true;
c = 0;
while(MoreText)
{
   wCursor.gotoEndOfWord(true);
   colorer = UnoRuntime.queryInterface(XPropertySet, nCursor);
   w = WordColor[c].getRGB();
   colorer.setPropertyValue("CharColor",new java.lang.Integer(w));
   c = (c + 1) % n;
   MoreText = wCursor.gotoNextWord(false);
}


Next, I wrote a c++ program to do the coloring, the point being that one can then call the .exe file from a macro. The program, whatever language it is in, has to establish a pipe or socket connection. In older Office versions it was necessary to start the listening process as discussed earlier, then have a special routine in the program to fetch the process. Nowadays the bootstrap for the ServiceManager automatically gets a pipe connection.

In c++, that looks like this:

Code: Select all   Expand viewCollapse view
   
   // Creates a simple registry service instance.
    Reference< XSimpleRegistry > xSimpleRegistry(
        ::cppu::createSimpleRegistry() );
   
       // Connects the registry to a persistent data source represented by a URL.
    xSimpleRegistry->open( OUString::createFromAscii("C:\\Documents and Settings\\Charlie\\My Documents\\Visual Studio 2010\\Projects\\ColorWords\\ColorWords.rdb"), sal_True, sal_False );
      
    Reference< XComponentContext > xComponentContext(::cppu::bootstrap_InitialComponentContext( xSimpleRegistry ) );
   
   Reference<XComponentContext> rComponentContext = ::cppu::bootstrap ();
   Reference<XMultiComponentFactory> xServiceManager = rComponentContext->getServiceManager ();
   Reference< XMultiServiceFactory > rOfficeServiceManager (xServiceManager,UNO_QUERY);



The SDK includes Java examples illustrating the same process.

Having gotten the ServiceManager above, we can use it to get the Desktop's CurrentComponent, which here we assume is going to be a text document:

Code: Select all   Expand viewCollapse view

        Reference < XInterface  > Desktop = rOfficeServiceManager->createInstance(OUString::createFromAscii( "com.sun.star.frame.Desktop" ));
      Reference< XDesktop > xDesktop(Desktop, UNO_QUERY);
      Reference< XComponent > xcomponent = xDesktop->getCurrentComponent();
      Reference< XTextDocument > xTextDoc (xcomponent, UNO_QUERY);
      Reference< XText > oText = xTextDoc->getText();
      


It should be similar in Java, and then you can use the xTextDoc to do whatever you want (like color the words).

Once you have the .exe, written in whatever language, you can call it from a javascript macro like so:

Code: Select all   Expand viewCollapse view

importClass(Packages.com.sun.star.uno.UnoRuntime);
importClass(Packages.com.sun.star.system.XSystemShellExecute);

xCompCont = XSCRIPTCONTEXT.getComponentContext();
xMultiComponentFactory = xCompCont.getServiceManager();

shell = xMultiComponentFactory.createInstanceWithContext('com.sun.star.system.SystemShellExecute', xCompCont);
xshell = UnoRuntime.queryInterface(XSystemShellExecute, shell);

xshell.execute("C:\\...path...\\ColorWords.exe","",0);



If you do this in a jscript macro, you can attach that macro to a button or a menu item as easily as you could a Basic macro. There is no need to call Java from basic, though that is possible.

Well, I'll be happen if I can get a single Java function called. I won't need anything fancy. And why is Open Office invisible if the document is adding a toolbar button to it?
Will Pittenger
I currently use OpenOffice 4.0 32-bit on Windows 7 64-bit (as of August 7th, 2013)
Will Pittenger
 
Posts: 45
Joined: Tue Dec 14, 2010 10:43 am
Location: Morton, IL

Re: How would I call a Java function from within OpenOffice

Postby Charlie Young » Sun Jun 17, 2012 11:47 pm

Will Pittenger wrote:Well, I'll be happen [sic.] if I can get a single Java function called. I won't need anything fancy. And why is Open Office invisible if the document is adding a toolbar button to it?


The soffice -invisible is a separate process, running in the background.

I will also be happy if you get a Java function called, and my suggestion above - which maybe isn't as complicated as I made it seem - offers one way to do it. I also realize that Java isn't the same as JavaScript, but I'm using that to show a way to call an .exe, which could be written in Java, because I think we're trying to minimize our use of Basic here. I also think you should probably concentrate on hol.stens tricks, which seem closer to what you're after than what I'm offering. You might also suggest what you might like your Java function to accomplish. I'm assuming, since you want to process a writer document , that you're more interested in what the function does to the document's preexisting condition exclusive of anything supplied by the functions return value - but I'm not really sure
Apache OpenOffice 4.1.1
Windows XP
User avatar
Charlie Young
Volunteer
 
Posts: 1559
Joined: Fri May 14, 2010 1:07 am


Return to External Programs

Who is online

Users browsing this forum: No registered users and 1 guest