mutercim
mutercim

Reputation: 31

A way to add subroutines by code at runtime in libreoffice basic

Is there a way to add / delete subroutines or functions by code at runtime in libreoffice basic?

I would very like to be able to create, delete and run subroutines or functions by code at runtime. I am considering this is as a way to bypass the lack of interfaces (inability of dependency inversion) in libreoffice-basic.

Upvotes: 0

Views: 97

Answers (1)

mutercim
mutercim

Reputation: 31

Thanks to JohnSUN. So it seems you can run a macro using a string name (although its hard). Just examine the following code.

Here is example code (too long, it is up to you to clean)

REM CALL A USER-DEFINED FUNCTION FROM AN ARBITRARY LIBRARY
REM Parameters: 
REM funcName - string - name of the user-defined function
REM inpParams - an array of parameters passed to the function (can be empty)
REM libName - string - library Name (default "Standard")
REM In case of an error (no library, no function found, error in the function itself)
REM returns Nothing. Otherwise, the result of execution
REM custom function with the specified parameters.
REM Author: Vladyslav Orlov aka JohnSUN, Ukraine, Kyiv, 2011
REM mailto: [email protected]
Function runMacro(funcName As String, Optional inpParams As Variant, Optional libName)
    Dim oScriptProvider As Object   
    Dim oLib As Object              
    Dim oScript As Object           
    Dim oModuleNames As Object      
    Dim i%                          
    Dim aOutParamIndex(), aOutParam()   ' Dummy arrays, read https://wiki.openoffice.org/wiki/Documentation/DevGuide/Scripting/Scripting_Framework_URI_Specification
    Dim macroName As String         
    Const prefix="vnd.sun.star.script:"
    Const suffix="?language=Basic&location=document"
    runMacro = Nothing
    If IsMissing(inpParams) Then inpParams = Array()
    If Not IsArray(inpParams) Then inpParams = Array(inpParams)
    If IsMissing(libName) Then libName = "Standard"
    BasicLibraries.LoadLibrary(libName)
    If NOT BasicLibraries.isLibraryLoaded(LibName) Then Exit Function
    oLib = BasicLibraries.getByName(libName)
    oScriptProvider = ThisComponent.ScriptProvider
    
    oModuleNames = oLib.getElementNames()
    On Local Error GOTO NextIteration
    For i = LBound(oModuleNames) To UBound(oModuleNames)
        macroName = prefix & libName & "." & oModuleNames(i) & "." & funcName & suffix
        oScript = oScriptProvider.getScript(macroName)
        runMacro = oScript.invoke(inpParams, aOutParamIndex, aOutParam)
        Exit Function
NextIteration:
    Next i
End Function

And below are the functions called:

REM Macros available for running:

Sub Main
    display("dum", "Fn0")
    display("dum", "Fn1")
End Sub

' FUNCTION USED

Sub display(sFuncName As String, Optional param)
  msgbox (runMacro(sFuncName, param))
End Sub 

Function dum(sFuncName As String) As String 
    dum = "This is DUM(" & sFuncName & "(0)) = " & runMacro(sFuncName, 0) & Chr(10) & _
          "and is DUM(" & sFuncName & "(1)) = " &   runMacro(sFuncName, 1)
End Function 

Function Fn0(iVal As Integer) As String 
    Fn0 = "From Fn0 (" & iVal & ") "
End Function 

Function Fn1(iVal As Integer) As Integer
Static add As Long 
    add = add + 5
    Fn1 = iVal + add
End Function 

Upvotes: 0

Related Questions