[Solved] Method "ScriptProvider.getScript()" not available

Creating a macro - Writing a Script - Using the API (OpenOffice Basic, Python, BeanShell, JavaScript)
Post Reply
mca0815
Posts: 2
Joined: Mon Sep 28, 2015 6:23 pm

[Solved] Method "ScriptProvider.getScript()" not available

Post by mca0815 »

Hello everybody!

I am trying to write a Delphi program that will open an ODT document and execute a macro that is located in this document.

I am using the following code:

Code: Select all

[...]
var
  FLibreOfficeManager, FLibreOfficeDesktop, FDocument, LParameters, LScriptProvider, LScript: OleVariant;  
begin
  [...]
  FLibreOfficeManager := CreateOleObject('com.sun.star.ServiceManager');
  FLibreOfficeDesktop := FLibreOfficeManager.createInstance('com.sun.star.frame.Desktop');
  LParameters := VarArrayCreate([0, -1], varVariant);
  FDocument := FLibreOfficeDesktop.LoadComponentFromURL('file:///C:/temp/Test.odt', '_blank', 0, LParameters);
  LScriptProvider := FDocument.getScriptProvider;
  LScript := LScriptProvider.getScript('vnd.sun.star.script:Standard.Module1.Main?language=Basic&location=document');
  [...]
end;
However when the program reaches the last line of the example above, I get the following exception:
Method 'getScript' not supported by automation object
I also tried the same using VBA in Excel:

Code: Select all


Sub Main()

  Dim ServiceManager As Object
  Dim StarDesktop As Object
  Dim Doc As Object
  Dim Url As String
  Dim Dummy() 'An (empty) array of PropertyValues
  Dim ScriptProvider As Object
  Dim Script As Object
  
  Url = "file:///C:/temp/Test.odt"
 
  Set ServiceManager = CreateObject("com.sun.star.ServiceManager")
  Set StarDesktop = ServiceManager.CreateInstance("com.sun.star.frame.Desktop")
  Set Doc = StarDesktop.loadComponentFromURL(Url, "_blank", 0, Dummy)

  Set ScriptProvider = Doc.getScriptProvider
  Set Script = ScriptProvider.getScript("vnd.sun.star.script:Standard.Module1.Main?language=Basic&location=document")
  [...]
End Sub
But this also fails at the "getScript" call with the following error:
Runtime Error '438': Object does not support this property or method
So I think Delphi 2010 is not the Culprit.

But, when I write a Basic macro in OpenOffice like the following, everything works fine.

Code: Select all

Sub Main

  Dim Doc As Object
  Dim Url As String
  Dim Dummy() 'An (empty) array of PropertyValues
  Dim SciptProvider As Object
  Dim Script As Object
   
  Url = "file:///C:/temp/Test.odt"
 
  Doc = StarDesktop.loadComponentFromURL(Url, "_blank", 0, Dummy)
  ScriptProvider = Doc.getScriptProvider
  Script = ScriptProvider.getScript("vnd.sun.star.script:Standard.Module1.Main?language=Basic&location=document")
  [...]
End Sub
I also tried to get a MasterScriptProvider from the ServiceManager:

Code: Select all

  
  [...]
  LMasterScriptProvider := FLibreOfficeManager.CreateInstance('com.sun.star.script.provider.MasterScriptProviderFactory');
  LScriptProvider := LMasterScriptProvider.CreateScriptProvider();
  LScript := LScriptProvider.GetScript("vnd.sun.star.script:Standard.Module1.Main?language=Basic&location=document");
  [...]
This works quite fine. The method "getScript" is found and can be called in this case! However it complains that the script can not be located. As far as I know (I am quite new to UNO, etc) this is because you can not access a script that is located in a document using the ScriptProvider this way?!

So please, do you have any idea why the method "getScript()" is not found when using the ScriptProvider of a document? Or as a workaround how one can call a script located in a document using the MasterScriptProvider like in the last code example?

PS: I also already tested opening the document using the MacroExecutionMode "ALWAYS_EXECUTE_NO_WARN". However the method still can not be found.
Last edited by mca0815 on Sat Oct 03, 2015 5:31 am, edited 2 times in total.
OpenOffice 4.1.1 on Windows 7 (64-Bit)
hanya
Volunteer
Posts: 885
Joined: Fri Nov 23, 2007 9:27 am
Location: Japan

Re: Method "Document.ScriptProvider.getScript()" not availab

Post by hanya »

I think this kind of problem has been posted in this forum but I'm not sure.
Could you wait a few seconds before to call getScriptProvider method for testing?

If you can not solve by the way above, you can try to make the script provider for the script container of the document like the following in Basic.
This is what internal code does to generate script provider for documents.

Code: Select all

Sub CreateDocumentScriptProvider
  mspf = GetDefaultContext().getByName("/singletons/com.sun.star.script.provider.theMasterScriptProviderFactory")
  sp = mspf.createScriptProvider(ThisComponent.ScriptContainer)
  script = sp.getScript("vnd.sun.star.script:Standard.Module1.Main?language=Basic&location=document")
  script.invoke(array(), array(), array())
End Sub
Please, edit this thread's initial post and add "[Solved]" to the subject line if your problem has been solved.
Apache OpenOffice 4-dev on Xubuntu 14.04
B Marcelly
Volunteer
Posts: 1160
Joined: Mon Oct 08, 2007 1:26 am
Location: France, Paris area

Re: Method "Document.ScriptProvider.getScript()" not availab

Post by B Marcelly »

Hi,
Years ago, I also found that I could not use the script provider to execute a Basic macro of a document.
My work-around is to use the dispatcher, which has drawbacks : no returned data, and only string arguments.

Anyway, running a macro of a document from an external program should be the last solution.
Bernard

OpenOffice.org 1.1.5 / Apache OpenOffice 4.1.1 / LibreOffice 5.0.5
MS-Windows 7 Home SP1
mca0815
Posts: 2
Joined: Mon Sep 28, 2015 6:23 pm

Re: Method "Document.ScriptProvider.getScript()" not availab

Post by mca0815 »

Hello hanya,
hello B Marcelly!

First I tried hanyas idea to wait some time. I created a test app where I had buttons for each of the lines of the Delphi code posted above. Then I pushed one after the other waiting at least one minute before pushing the next button. But this still did not make the method "appear". Same error.

I also tried your second suggestion. I think this should be the Delphi version of it:

Code: Select all

  FLibreOfficeManager := CreateOleObject('com.sun.star.ServiceManager');
  LMasterScriptProvider := FLibreOfficeManager.DefaultContext.GetByName('/singletons/com.sun.star.script.provider.theMasterScriptProviderFactory');
  LScriptProvider := LMasterScriptProvider.CreateScriptProvider(FDocument.ScriptContainer);
  LScript := LScriptProvider.GetScript('vnd.sun.star.script:Standard.Module1.Main?language=Basic&location=document');
  LScript.Invoke;
Unfortunately still the same error. Missing "getScript" method.

This let me try B Marcellys idea using the Dispatcher resulting in following code:

Code: Select all

  LParameters := VarArrayCreate([0, -1], varVariant);
  LDispatcher := FLibreOfficeManager.CreateInstance('com.sun.star.frame.DispatchHelper');
  LDispatcher.ExecuteDispatch(FLibreOfficeDesktop.CurrentFrame, 'vnd.sun.star.script:Standard.Module1.Main?language=Basic&location=document', '', 0, LParameters);
This indeed did work. But unfortunately only as long as the document is opened visible. But I want to be the document hidden during the initialization of the document to which running the script belongs.

After that I did a forum search using the additional search term "hidden" which brought up the following thread. Apparently this is the one hanya had in mind and which I apparently did not find during my searches before opening this thread.
Run document macros via API if Desktop is hidden
viewtopic.php?f=20&t=32051&p=146883
And in this thread, hanya, you mention that you are able to access the method using introspection.

I was not aware of introspection by now. So I tried this, and yeeeeees, this also works with Delphi!

So, thank you very much for your help! Without the input of you both, I would not have found the solution. :bravo:

Down below there is a working Delphi routine to load the document and invoke the script in it.

Code: Select all

procedure LaunchMacro;
const
  ALWAYS_EXECUTE_NO_WARN = 4;
var
  LLibreOfficeManager: OleVariant;
  LLibreOfficeDesktop: OleVariant;
  LUri: string;
  LDocument: OleVariant;
  LScriptProvider: OleVariant;
  LIntrospection: OleVariant;
  LInspectedProvider: OleVariant;
  LInspectedMethod: OleVariant;
  LScript: OleVariant;
  LParameters: OleVariant;

  function MakePropertyValue(APropertyName: string; AValue: OleVariant): OleVariant;
  var
    LResult: OleVariant;
  begin
    LResult := LLibreOfficeManager.Bridge_GetStruct('com.sun.star.beans.PropertyValue');
    LResult.Name := APropertyName;
    LResult.Value := AValue;
    Result := LResult;
  end;

begin
  { Init OpenOffice }
  LLibreOfficeManager := CreateOleObject('com.sun.star.ServiceManager');
  LLibreOfficeDesktop := LLibreOfficeManager.CreateInstance('com.sun.star.frame.Desktop');

  { Load document }
  LParameters := VarArrayCreate([0, 0], varVariant);
  LParameters[0] := MakePropertyValue('MacroExecutionMode', ALWAYS_EXECUTE_NO_WARN);
  LUri := FilenameToUriStr('C:\temp\test.odt', [fuPlainColon]);
  LDocument := LLibreOfficeDesktop.LoadComponentFromURL(LUri, '_blank', 0, LParameters);

  { Get script provider }
  LScriptProvider := LDocument.GetScriptProvider;

  { Get "GetScript" method from script provider by introspection }
  LIntrospection := LLibreOfficeManager.CreateInstance('com.sun.star.beans.Introspection');
  LInspectedProvider := LIntrospection.Inspect(LScriptProvider);
  LInspectedMethod := LInspectedProvider.GetMethod('getScript', -1);

  { Call "GetScript" method }
  LParameters := VarArrayCreate([0, 0], varVariant);
  LParameters[0] := 'vnd.sun.star.script:Standard.Module1.Main?language=Basic&location=document';
  LScript := LInspectedMethod.Invoke(LScriptProvider, LParameters);

  { Execute script }
  VarArrayRedim(LParameters, -1);
  LScript.Invoke(LParameters, LParameters, LParameters);  // No Parameters neccessary for my needs
end;
OpenOffice 4.1.1 on Windows 7 (64-Bit)
B Marcelly
Volunteer
Posts: 1160
Joined: Mon Oct 08, 2007 1:26 am
Location: France, Paris area

Re: [SOLVED] Method "ScriptProvider.getScript()" not availab

Post by B Marcelly »

The object obtained by getScriptProvider is not correctly build, and hanya's code works around this bug.
The original code does not work in Apache OpenOffice 4.1.1 (and older) but it works in LibreOffice 4.4.5. It may be due to some API modifications.

However the object obtained by getScriptProvider is really bugged. This can be seen in OpenOffice Basic, both in Apache OpenOffice and LibreOffice. Xray shows that methods hasElements and getElementNames exist. But if you try to use them, an error occurs, that is not same as when typing an incorrect method name.

Code: Select all

Dim sp as variant, v as variant
sp = thisComponent.getScriptProvider()
v = sp.getElementNames() ' error : getElementNames not implemented !!!
v = sp.hasElements ' error : hasElements not implemented !!!
This inconsistency was described in Bug 70645, years ago.
Bernard

OpenOffice.org 1.1.5 / Apache OpenOffice 4.1.1 / LibreOffice 5.0.5
MS-Windows 7 Home SP1
hanya
Volunteer
Posts: 885
Joined: Fri Nov 23, 2007 9:27 am
Location: Japan

Re: [SOLVED] Method "ScriptProvider.getScript()" not availab

Post by hanya »

B Marcelly wrote:However the object obtained by getScriptProvider is really bugged. This can be seen in OpenOffice Basic, both in Apache OpenOffice and LibreOffice. Xray shows that methods hasElements and getElementNames exist. But if you try to use them, an error occurs, that is not same as when typing an incorrect method name.
They just raises exceptions in their implementations [1].
css.container.XNameContainer interface is used to manage scripts which provided by extension packages. Only hasByName, insertByName and removeByName are used. The reuse of the interface gave us the strange behaviour in this case. In the case of the script provider for Basic, XNameContainer interface is not implemented, because marging the basic libraries installed as part of extensions are processed differently.

[1] http://svn.apache.org/viewvc/openoffice ... arkup#l774
Please, edit this thread's initial post and add "[Solved]" to the subject line if your problem has been solved.
Apache OpenOffice 4-dev on Xubuntu 14.04
Post Reply