Solved: How to call JavaScript function from Basic

I have searched for this and found numerous responses for how to attach a JavaScript function to a button or event, but I have not found the answer to this question.

To explain: I want to apply a regex to a given string and return the result. I can find no way of doing this in Basic, so decided to write it in JavaScript. The function is very simple, but I can’t see how to invoke it from Basic. The ‘Invoke’ method is self-explanatory, but it seems I need to establish some kind of environment for the invocation first.

Am I missing something obvious?

Any help would be appreciated.

Thanks,
Doug


much later:

I am almost there, but not quite.

I have a javascript function:

/* Applies strReplace to all instances of strRegexp in strSearch and returns the result */
function jsRegExp(strSearch, strRegexp, strReplace) {
	var strRetVal;
	strRetVal = strSearch.replace(strRegexp, strReplace);
	return strRetVal;
}

and an LO Basic subroutine:

Sub CallJavaScript
    Dim oScriptProvider, oScript
    Dim aParams(), aOutParamIndex(), aOutParam()
    Dim MyArray(2)
    MyArray(0)="John O'Brien"
    MyArray(1)="'"
    MyArray(2)="''"
    oScriptProvider = ThisComponent.getScriptProvider()
    oScript = oScriptProvider.getScript( "vnd.sun.star.script:abpaJavaScripts.jsRegExp.js?language=JavaScript&location=document" )
	oScript.invoke( MyArray, aOutParamIndex, aOutParam)
End Sub

I intend the javascript to be extended after I get this much working.

If I call the javascript as follows, it works fine:

/* Harness to test jsRegExp */
var strFixedIt = jsRegExp("John O'Brien","'","''");

but called from the Basic sub, all I get is the arrays aOutParamIndex() and aOutParam() sized (0 to-1) in the watched variable list.

Am I trying to do something impossible, have I misunderstood what I have been told, or is my code incorrect?

It’s a good thing I am doing this for charity, because I could not charge for the hours I have spent on it [grin].

As always, any help would be greatly appreciated.

If the answer solves your question please tick the :heavy_check_mark:.

Search and replace all with regular expression it’s possible in Basic…

Look this: Scripting Framework URI Specification - Apache OpenOffice Wiki

With EasyDev you can call macros in others languages:
http://easydev.readthedocs.io/en/latest/tools.html#call-macros

Best regards

Thanks mauricio - the Wiki entry was exactly what I was looking for.

could you please share your solution, i try to get json object data from .js into the spreadsheet

Here is a sample:

Sub CallJavaScript
    Dim oScriptProvider, oScript
    Dim aParams(), aOutParamIndex(), aOutParam()
    oScriptProvider = ThisComponent.getScriptProvider()
    oScript = oScriptProvider.getScript( "vnd.sun.star.script:ModifySpreadsheet.modifysheet.js?language=JavaScript&location=user" )
    oScript.invoke( aParams(), aOutParamIndex(), aOutParam() )
End Sub

The only lines which should need changes:

  • if any parameter need to be sent they go in aParams()

  • in defining string for oScript provider, actual script name & location of script (here it is user)

  • if return it needs adding on ‘invoke’ line

Please refer to docs mentioned by @mauricio

Edit 7/20/2017:

The problems you are having all have to do with parameters. While I have barely dealt with javascript (only second time), from using python I was fairly certain ‘aOutParamIndex()’ & ‘aOutParam’ did not come into play here.

The parameters in javascript enter as ARGUMENTS[0] and the only way I found for a return was eval.

Here is the code I used successfully:

BASIC:

Sub PrintMyOS
    Dim aParams(0), aOutParamIndex(0), aOutParam(0)
    Dim MyArray(2)
    MyArray(0)="John O'Brien"
    MyArray(1)="'"
    MyArray(2)="''"
    aParams(0) = MyArray
    oScriptProvider = ThisComponent.getScriptProvider()
 'Replace this oScript line with yours'
  oScript = oScriptProvider.getScript( "vnd.sun.star.script:ModifySpreadsheet.modifysheet.js?language=JavaScript&location=user" )
    x = oScript.invoke( aParams, aOutParamIndex, aOutParam)
    print x
End Sub

FYI: I placed my script in the user section under the folder ModifySpreadsheet with a script name of modifysheet.js. Not descriptive for this application; was just using something had from first go at a javascript. But this should explain my oScript statement.

javascript:

event = ARGUMENTS[0];

strSearch = event[0];
strRegexp = event[1];
strReplace = event[2];

var strFixedIt = jsRegExp(strSearch, strRegexp, strReplace);

eval(strFixedIt);

function jsRegExp(strSearch, strRegexp, strReplace) {
    var strRetVal;
    strRetVal = strSearch.replace(strRegexp, strReplace);
    return strRetVal;
}

Now I’ll be the first to say the javascript code may not be the best but it works.

Edit 08/10/2017:

Here’s where I am. Took your code (copy & paste) and names and set up in user directory:

image description

You can see my original ‘ModifySpreadsheet’ just below the script with your names.

Used your Basic code & Javascript code (BOTH ways) and got the correct result each time:

BTW your comment about eval() not needed worked for me this time (may have some ideas about that). Again, only second time ever using Javascript.

Now the only thing never discussed has been ‘parcel-descriptor.xml’. Here is the contents I used on this last test:

<?xml version="1.0" encoding="UTF-8"?>
<!--
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * This file incorporates work covered by the following license notice:
 *
 *   Licensed to the Apache Software Foundation (ASF) under one or more
 *   contributor license agreements. See the NOTICE file distributed
 *   with this work for additional information regarding copyright
 *   ownership. The ASF licenses this file to you under the Apache
 *   License, Version 2.0 (the "License"); you may not use this file
 *   except in compliance with the License. You may obtain a copy of
 *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
-->
<parcel language="JavaScript" xmlns:parcel="scripting.dtd">

    <script language="JavaScript">
        <locale lang="en">
            <displayname value="ModifySpreadsheet"/>
            <description>Just a test
            </description>
        </locale>
        <functionname value="jsRegExp.js"/>
        <logicalname value="abpaJavaScripts.JavaScript"/>
    </script>

</parcel>

At this point I have no other answers. Everything I try works. My code, your code both ways. Have executed the code from the Basic IDE and from a push button on a spreadsheet, all with the correct results. Can’t get the error you seem to get.

If this answers your question please click on the :heavy_check_mark: (upper left area of my answer).

Hi Ratslinger. That is what I was looking for. I knew I had seen it somewhere, but lost track of it. Thanks very much.

I have copied & pasted the new lines dealing with arguments, but now I get the error: “BASIC runtime error”, "An exception occurred ", “Type: com.sun.star.script.provider.ScriptFrameworkErrorException”, “Message: Cannot read property “0” from undefined”
I don’t know whether it is complaining about ARGUMENTS[0] or event[0]. Suggestions? I will keep trying.

If I use the code var event = ARGUMENTS[0]; var strSearch = event[0];
I get the above error on line 2. If I have the code var event = ARGUMENTS; I get the error “Cannot read property “replace” from undefined.” at the line ‘strRetVal = strSearch.replace(strRegexp, strReplace);’. Still trying.

The problem, as stated in your error message, is in the Basic Code. I can duplicate if not set correctly. Compare your code to mine. The code presented works. Just double checked.

Hi Ratslinger and thanks for replying. I have copied your Basic and JavaScript code from this page and pasted them into my respective editors. Attempting to run the Basic code results in the error 'Cannot read property “0” from undefined" '. This is at the statement ‘strSearch = event[0]’. I think something must be wrong with my system?

Making some progress. The following script returns the correct result to Basic:`event = ARGUMENTS[0];

strSearch = “John O’Brien”;
strRegexp = “’”;
strReplace = “’’”;
jsRegExp(strSearch, strRegexp, strReplace);

/*var strFixedIt = jsRegExp(strSearch, strRegexp, strReplace);

eval(strFixedIt);*/

function jsRegExp(strSearch, strRegexp, strReplace) {
var strRetVal;
strRetVal = strSearch.replace(strRegexp, strReplace);
return strRetVal;
}`
Still can’t pass variables into JavaScript. :frowning:

By the way, I am also discussing this problem here with Villeroy et al.

Based upon the code you posted in the other forum, the Basic portion is definitely not what I posted here. You posted it multiple times and nothing close. At the very lease, these lines were different:

 Dim aParams(0), aOutParamIndex(0), aOutParam(0)
    aParams(0) = MyArray
    x = oScript.invoke( aParams, aOutParamIndex, aOutParam)

Don’t think it’s your system. Think it’s your code. It may help if you post exactly what you say is a copy of mine that fails.

You don’t comprehend the array situation. Your three parameters need to go into MyArray. That array then needs to go into aParams(0). The invoke statement sends your three parameters all bundled as aParams and sent to the Javascript where they are separated and used. The other parameters in the invoke statement are never used but MUST be defined as stated.

Hi Ratslinger. Thanks very much for your continuing assistance.

As requested, here is my Basic macro:

    Sub PrintMyOS
            Dim aParams(0), aOutParamIndex(0), aOutParam(0)
            Dim MyArray(2) As String
            MyArray(0)="John O'Brien"
            MyArray(1)="'"
            MyArray(2)="''"
            aParams(0) = MyArray
            oScriptProvider = ThisComponent.getScriptProvider()
         'Replace this oScript line with yours'
         'oScript = oScriptProvider.getScript( "vnd.sun.star.script:ModifySpreadsheet.modifysheet.js?language=JavaScript&location=user" )
            oScript = oScriptProvider.getScript( "vnd.sun.star.script:abpaJavaScripts.jsRegExp.js?language=JavaScript&location=user" )
            x = oScript.invoke( aParams, aOutParamIndex, aOutParam)
            print x
End Sub

This calls the following JavaScript:

// Get the ActionEvent object from the ARGUMENTS list
event = ARGUMENTS[0];

strSearch = "John O'Brien";
strRegexp = "'";
strReplace = "''";

jsRegExp(strSearch, strRegexp, strReplace);

function jsRegExp(strSearch, strRegexp, strReplace) {
    var strRetVal;
    strRetVal = strSearch.replace(strRegexp, strReplace);
    return strRetVal;
}

As written above, the JavaScript returns the correct - expected - value to Basic. If I change the assignments to:

strSearch = event[0];
strRegexp = event[1];
strReplace = event[2];

as per your example, Basic returns an error at strSearch = event[0]:

BASIC runtime error. An exception
occurred Type:
com.sun.star.script.provider.ScriptFrameworkErrorException
Message: Cannot read property “0” from
undefined.

At present I am using Packages.com.sun.star.uno.AnyConverter to investigate the nature of the parameters ‘seen’ by JavaScript. It appears ARGUMENTS[0] contains an array of strings, but I have not been able to extract anything from the array as yet.

I realise my code does not use the eval() construct you use, but the code as above does work.

I will keep bashing away, because the solution seems so close now.

SOLVED IT!!! Please see explanation at link text