CalcFunctions

From Apache OpenOffice Wiki
Jump to: navigation, search

Originally posted in oooForum here. This code tries to introduce native Calc functions coded in Python. This article is related to the Python series page tutorials.

This code deals with:

  1. Develop a trivial Calc function add on in Python.
  2. To be followed by more sophisticated functions.
  3. To be followed by eventually running a Poll on OOoForum asking what kind of functions shoudl be developed. (PLEASE don't post any answers to this question AT THIS TIME. This post is a ROADMAP, NOT A REQUEST for ideas.)
  4. Build a canned example, posted to OOoForum that is specifically designed for easy cloning and creation of new Calc functions.


The code has several issues, please read the forum topic for more detail issues on this code, also remember this code was never really debugged and is pretty old. So you are on your own. If you have a more update version or discover workarounds, please update the wiki.

import sys 
import unohelper 
 
from com.sun.star.sheet import XAddIn 
from com.sun.star.sheet import XCompatibilityNames 
 
from com.sun.star.lang import XServiceName 
from com.sun.star.lang import XLocalizable 
 
g_ImplementationHelper = unohelper.ImplementationHelper() 
 
 
class DannysCalcFunctions1( unohelper.Base, XAddIn, XLocalizable, XCompatibilityNames, XServiceName ): 
    # The component must have a ctor with the component context as argument. 
    def __init__( self, oContext ): 
        self.oContext = oContext 
        self.oCoreReflection = None 
        self.StarDesktop = None 
        self.getDesktop() 
 
    #---------------------------------------- 
    #   Danny's stuff to make programming less convenient. 
    #---------------------------------------- 
 
    def getServiceManager( self ): 
        """Get the ServiceManager from the running OpenOffice.org. 
        """ 
        return self.oContext.ServiceManager 
 
    def createUnoService( self, cClass ): 
        """A handy way to create a global objects within the running OOo. 
        """ 
        oServiceManager = self.getServiceManager() 
        oObj = oServiceManager.createInstance( cClass ) 
        return oObj 
 
    def getDesktop( self ): 
        """An easy way to obtain the Desktop object from a running OOo. 
        """ 
        if self.StarDesktop == None: 
            self.StarDesktop = self.createUnoService( "com.sun.star.frame.Desktop" ) 
        return self.StarDesktop 
 
    def getCoreReflection( self ): 
        if self.oCoreReflection == None: 
            self.oCoreReflection = self.createUnoService( "com.sun.star.reflection.CoreReflection" ) 
        return oCoreReflection 
 
    def createUnoStruct( self, cTypeName ): 
        """Create a UNO struct and return it. 
        """ 
        oCoreReflection = self.getCoreReflection() 
 
        # Get the IDL class for the type name 
        oXIdlClass = oCoreReflection.forName( cTypeName ) 
 
        # Create the struct. 
        oReturnValue, oStruct = oXIdlClass.createObject( None ) 
 
        return oStruct 
 
    def makePropertyValue( self, cName=None, uValue=None, nHandle=None, nState=None ): 
        """Create a com.sun.star.beans.PropertyValue struct and return it. 
        """ 
        oPropertyValue = self.createUnoStruct( "com.sun.star.beans.PropertyValue" ) 
 
        if cName != None: 
            oPropertyValue.Name = cName 
        if uValue != None: 
            oPropertyValue.Value = uValue 
        if nHandle != None: 
            oPropertyValue.Handle = nHandle 
        if nState != None: 
            oPropertyValue.State = nState 
 
        return oPropertyValue 
 
 
 
    #---------------------------------------- 
    #   Inconvenience routines for working with structs needed later 
    # 
 
    def makeLocale( self, cLanguage="", cCountry="", cVariant="" ): 
        oLocale = self.createUnoStruct( "com.sun.star.lang.Locale" ) 
        oLocale.Language = cLanguage 
        oLocale.Country = cCountry 
        oLocale.Variant = oVariant 
        return oLocale 
 
    def makeLocalizedName( self, stLocale, cName ): 
        oLocalizedName = self.createUnoStruct( "com.sun.star.sheet.LocalizedName" ) 
        oLocalizedName.Locale = stLocale 
        oLocalizedName.Name = cName 
        return oLocalizedName 
 
 
 
 
    #---------------------------------------- 
    #   Interface: XAddIn 
    #   Inherits from...    XLocalizable 
    #---------------------------------------- 
 
    # string 
    # getProgrammaticFuntionName( [in] string aDisplayName ); 
    # Note: the method name spelling error is in the API! 
    def getProgrammaticFuntionName( self, cDisplayFnName ): 
        if cDisplayFnName == "AddFive": 
            return "nom.DannyBrewer.test.DannysCalcFunctions1.AddFive" 
        elif cDisplayFnName == "AddSix": 
            return "nom.DannyBrewer.test.DannysCalcFunctions1.AddSix" 
        return "" 
 
    # string 
    # getDisplayFunctionName( [in] string aProgrammaticName ); 
    def getDisplayFunctioName( self, cProgrammaticFnName ): 
        if cProgrammaticFnName == "nom.DannyBrewer.test.DannysCalcFunctions1.AddFive": 
            return "AddFive" 
        elif cProgrammaticFnName == "nom.DannyBrewer.test.DannysCalcFunctions1.AddSix": 
            return "AddSix" 
        return "" 
 
    # string 
    # getFunctionDescription( [in] string aProgrammaticName ); 
    def getFunctionDescription( self, ccProgrammaticFnName ): 
        if cProgrammaticFnName == "nom.DannyBrewer.test.DannysCalcFunctions1.AddFive": 
            return "Adds five to the argument." 
        elif cProgrammaticFnName == "nom.DannyBrewer.test.DannysCalcFunctions1.AddSix": 
            return "Add six to the argument." 
        return "" 
 
    # string 
    # getDisplayArgumentName( [in] string aProgrammaticName 
    #                         [in] long   nArgument ); 
    def getDisplayArgumentName( self, ccProgrammaticFnName, nArgNum ): 
        if cProgrammaticFnName == "nom.DannyBrewer.test.DannysCalcFunctions1.AddFive": 
            if nArgNum == 0: 
                return "number" 
        elif cProgrammaticFnName == "nom.DannyBrewer.test.DannysCalcFunctions1.AddSix": 
            if nArgNum == 0: 
                return "number" 
        return "" 
 
    # string 
    # getArgumentDescription( [in] string aProgrammaticName 
    #                         [in] long   nArgument ); 
    def getArgumentDescription( self, ccProgrammaticFnName, nArgNum ): 
        if cProgrammaticFnName == "nom.DannyBrewer.test.DannysCalcFunctions1.AddFive": 
            if nArgNum == 0: 
                return "A number to which five will be added." 
        elif cProgrammaticFnName == "nom.DannyBrewer.test.DannysCalcFunctions1.AddSix": 
            if nArgNum == 0: 
               return "A number to which six will be added." 
        return "" 
 
    # string 
    # getProgrammaticCategoryName( [in] string aProgrammaticName ); 
    def getProgrammaticCategoryName( self, ccProgrammaticFnName ): 
        if cProgrammaticFnName == "nom.DannyBrewer.test.DannysCalcFunctions1.AddFive": 
            return "Add-In" 
        elif cProgrammaticFnName == "nom.DannyBrewer.test.DannysCalcFunctions1.AddSix": 
            return "Add-In" 
        return "" 
 
    # string 
    # getDisplayCategoryName( [in] string aProgrammaticName ); 
    def getDisplayCategoryName( self, ccProgrammaticFnName ): 
        if cProgrammaticFnName == "nom.DannyBrewer.test.DannysCalcFunctions1.AddFive": 
            return "Add-In" 
        elif cProgrammaticFnName == "nom.DannyBrewer.test.DannysCalcFunctions1.AddSix": 
            return "Add-In" 
        return "" 
 
    #---------------------------------------- 
    #   Interface: XCompatibilityNames 
    #---------------------------------------- 
 
    # sequence< LocalizedName > 
    # getCompatibilityNames( [in] string aProgrammaticName ); 
    def getCompatibilityNames( self, ccProgrammaticFnName ): 
        if cProgrammaticFnName == "nom.DannyBrewer.test.DannysCalcFunctions1.AddFive": 
            return ( 
                self.makeLocalizedName( self.makeLocale( "en", "US", "" ), 
                                        "AddFive" ) 
                ,) 
        elif cProgrammaticFnName == "nom.DannyBrewer.test.DannysCalcFunctions1.AddSix": 
            return ( 
                self.makeLocalizedName( self.makeLocale( "en", "US", "" ), 
                                        "AddSix" ) 
                ,) 
        return () 
 
    #---------------------------------------- 
    #   Interface: XLocalizable 
    #   This is here because XAddIn inherits it. 
    #---------------------------------------- 
 
    # void 
    # setLocale( [in] Locale eLocale ); 
    def setLocale( self, stLocale ): 
        return 
 
    # Locale 
    # getLocale(); 
    def getLocale( self ): 
        return self.makeLocale( "en", "US", "" ) 
 
    #---------------------------------------- 
    #   Interface: XServiceName 
    #---------------------------------------- 
 
    # string 
    # getServiceName(); 
    def getServiceName( self ): 
        return "nom.DannyBrewer.test.DannysCalcFunctions1" 
 
 
 
# add the class to the implementation container, 
# which the loader uses to register/instantiate the component. 
g_ImplementationHelper.addImplementation( \ 
        # The class 
   DannysCalcFunctions1, 
        # The implementation name. 
        # Change this name for your own service. 
        "nom.DannyBrewer.test.DannysCalcFunctions1", 
        # A list of services that that are implemented. 
   ("com.sun.star.sheet.AddIn",), )

Final notes on the code by danny: It is also worth noting that I have not figured out where to actually implement the two functions AddFive() and AddSix(). All of the above is just the infrastructure for making the two functions and their descriptions and argument lists known to Calc.

I still have to finish reading the above linked section of the Developer's Guide again. Maybe I can figure out what I'm missing. Or maybe there is a fully working Calc function example somewhere else (even in a different language?) that I can examine?

Personal tools