[Python] Cannot successfully create the simplest LibreOffice extension for UDF's

Discussão em 'Python' iniciado por Stack, Agosto 29, 2025.

  1. Stack

    Stack Membro Participativo

    New here. Beginner with Python and LibreOffice. Some experience with C#. OS: Win 11 LO: 25.8

    I have been trying to learn how to create a LO extension to provide UDF's for use in LO Calc. I have dozens of UDF's written in C# that work just fine in Excel, but I want to transition to LO.

    I tried C# but failed. I tried Java, didn't really like it, but failed anyway. Now I'm trying Python (thinking it might be easier to get going). I have even tried using Eclipse but it seems very buggy (unless it's just me). I've suffered from trying to digest sometimes fragmented documentation, many contradictory snippets of info spread across many years of development, broken links etc. but I mustn't grumble as an ignoramus.

    So, I have made a python extension - very simple - just to establish a process I can follow. It contains only two test functions. The manifest, description, py, and idl files get compresses and changed to oxt. So far so good. This installs in LO extension manager. The two functions are visible in the formula bar and I can populate them with arguments (cell refs). So I have got further than before. However, the result is Error 504. The result of the two functions should be a simple arithmetical test.

    I am obviously missing something and I'm in the dark. Can anyone point me in the right direction please?

    The example is ragged, very simplistic and clearly the work of a beginner. I am pasting text of the main files concerned - each is quite short:

    LOEngFunc.py:
    *******************************************************************
    import uno
    import unohelper

    from com.sun.star.task import XJobExecutor
    from com.rabeeton.LOEngFunc import XLOEngFunc

    # LOEngFunc LOo Calc Add-in implementation.
    # Created by andy-beeton@rabeeton.com August 2025.

    ID_EXTENSION = 'com.rabeeton.LOEngFuncImpl'
    #SERVICE = ('com.sun.star.sheet.Addin',)
    SERVICE = ('com.sun.star.task.JobExecutor',)

    CTX = uno.getComponentContext()
    SM = CTX.getServiceManager()

    ERR_RTN_NUM = -1
    ERR_RTN_STR = "ERROR"
    INV_RTN_STR = "NO RESULT"

    class LOEngFuncImpl( unohelper.Base, XJobExecutor ):

    def __init__( self, ctx ):
    self.ctx = ctx
    self.dispatchhelper = self.createUnoService("com.sun.star.frame.DispatchHelper")

    def LOTest1( self, a, b ):
    try:
    return a * b
    except:
    return INV_RTN_STR

    def LOTest2( self, a, b ):
    try:
    return a / b
    except:
    return INV_RTN_STR

    def create_instance(sname, with_context=False):
    if with_context:
    instance = SM.createInstanceWithContext(sname, CTX)
    else:
    instance = SM.createInstance(sname)
    return instance

    g_ImplementationHelper = unohelper.ImplementationHelper()
    g_ImplementationHelper.addImplementation(LOEngFuncImpl, ID_EXTENSION, SERVICE)
    *******************************************************************

    root\idl\XLOENgFunc.idl:
    *******************************************************************
    include <com/sun/star/uno/XInterface.idl>

    module com
    {
    module rabeeton
    {
    interface XLOEngFunc
    {
    any LOTest1( [in] long a, [in] long b );
    any LOTest2( [in] double a, [in] double b );
    };

    service LOEngFunc : XLOEngFunc
    {
    service com::sun::star::sheet::AddIn;
    };
    };
    };
    *******************************************************************

    root\META-INF\manifest.xml
    *******************************************************************
    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE manifest:manifest PUBLIC "-//OpenOffice.org//DTD Manifest
    1.0//EN" "Manifest.dtd">
    <manifest:manifest
    xmlns:manifest="http://openoffice.org/2001/manifest">
    <manifest:file-entry manifest:media-type="application/vnd.sun.star.uno-component;type=Python"
    manifest:full-path="LOEngFunc.py" />
    <manifest:file-entry manifest:media-type="application/vnd.sun.star.package-bundle-description;locale=en"
    manifest:full-path="pkg-desc/pkg-description.en"/>
    <manifest:file-entry manifest:media-type="application/vnd.sun.star.configuration-data"
    manifest:full-path="CalcAddIn.xcu"/>
    </manifest:manifest>
    *******************************************************************

    root\description.xml
    *******************************************************************
    <?xml version='1.0' encoding='UTF-8'?>
    <description xmlns="http://openoffice.org/extensions/description/2006" xmlns:dep="http://openoffice.org/extensions/description/2006" xmlns:xlink="http://www.w3.org/1999/xlink">
    <identifier value="com.rabeeton.LOEngFunc"/>
    <version value="1.0"/>
    <registration>
    <simple-license accept-by="admin" default-license-id="ID0" suppress-on-update="true"
    ><license-text xlink:href="registration/license.txt" lang="en" license-id="ID0"
    /></simple-license>
    </registration>
    <publisher>
    <name xlink:href="mailto:andy-beeton@rabeeton.com">R A Beeton</name>
    </publisher>
    <display-name>
    <name>LO Engineering Functions</name>
    </display-name>
    </description>
    *******************************************************************

    root\CalcAddin.xcu
    *******************************************************************
    <?xml version="1.0" encoding="UTF-8"?>
    <oor:component-data xmlns:eek:or="http://openoffice.org/2001/registry" xmlns:xs="http://www.w3.org/2001/XMLSchema" oor:name="CalcAddIns" oor:package="org.openoffice.Office">
    <node oor:name="AddInInfo">
    <node oor:name="com.rabeeton.LOEngFunc.python.LOEngFuncImpl" oor:eek:p="replace">
    <node oor:name="AddInFunctions">
    <node oor:name="LOTest1" oor:eek:p="replace">
    <prop oor:name="DisplayName"><value xml:lang="en">LOTest1</value></prop>
    <prop oor:name="Description"><value xml:lang="en">Just a test.</value></prop>
    <prop oor:name="Category"><value>Add-In</value></prop>
    <prop oor:name="CompatibilityName"><value xml:lang="en">AutoAddIn.rabeeton.LOTest1</value></prop>
    <node oor:name="Parameters">
    <node oor:name="a" oor:eek:p="replace">
    <prop oor:name="DisplayName"><value xml:lang="en">a</value></prop>
    <prop oor:name="Description"><value xml:lang="en">The first integer.</value></prop>
    </node>
    <node oor:name="b" oor:eek:p="replace">
    <prop oor:name="DisplayName"><value xml:lang="en">b</value></prop>
    <prop oor:name="Description"><value xml:lang="en">The second integer.</value></prop>
    </node>
    </node>
    </node>
    <node oor:name="LOTest2" oor:eek:p="replace">
    <prop oor:name="DisplayName"><value xml:lang="en">LOTest2</value></prop>
    <prop oor:name="Description"><value xml:lang="en">Just another test.</value></prop>
    <prop oor:name="Category"><value>Add-In</value></prop>
    <prop oor:name="CompatibilityName"><value xml:lang="en">AutoAddIn.rabeeton.LOTest2</value></prop>
    <node oor:name="Parameters">
    <node oor:name="a" oor:eek:p="replace">
    <prop oor:name="DisplayName"><value xml:lang="en">a</value></prop>
    <prop oor:name="Description"><value xml:lang="en">The first floating point number.</value></prop>
    </node>
    <node oor:name="b" oor:eek:p="replace">
    <prop oor:name="DisplayName"><value xml:lang="en">b</value></prop>
    <prop oor:name="Description"><value xml:lang="en">The second floating point number.</value></prop>
    </node>
    </node>
    </node>
    </node>
    </node>
    </node>
    </oor:component-data>
    *******************************************************************

    Continue reading...

Compartilhe esta Página