1

I started Libre-Office Calc with the following command:

$ libreoffice --calc --accept="socket,host=localhost,port=2002;urp;StarOffice.ServiceManager"

import uno

# Class so I don't have to do this crap over and over again...
class UnoStruct():
    localContext = None
    resolver = None
    ctx = None
    smgr = None
    desktop = None
    model = None
    def __init__(self ):
        print("BEGIN: constructor")
        # get the uno component context from the PyUNO runtime
        localContext = uno.getComponentContext()

        # create the UnoUrlResolver
        resolver = localContext.ServiceManager.createInstanceWithContext("com.sun.star.bridge.UnoUrlResolver", localContext )

        # connect to the running office
        ctx = resolver.resolve( "uno:socket,host=localhost,port=2002;urp;StarOffice.ComponentContext" )
        smgr = ctx.ServiceManager

        # get the central desktop object
        desktop = smgr.createInstanceWithContext( "com.sun.star.frame.Desktop",ctx)

        # access the current writer document
        model = desktop.getCurrentComponent()

        print("END: constructor")

And then I call it with:

myUno = UnoStruct()
BEGIN: constructor
END: constructor

And attempt to get it with

active_sheet = myUno.model.CurrentController.ActiveSheet

AttributeError: 'NoneType' object has no attribute 'CurrentController'

and it appears that the model is None (null)

>>> active_sheet = myUno.model
>>> print( myUno.model )
None
>>> print( myUno )
<__main__.UnoStruct object at 0x7faea8e06748>

So what happened to it in the constructor? Shouldn't it still be there? I'm trying to avoid the boiler plate code.

leeand00
  • 25,510
  • 39
  • 140
  • 297
  • P.S. I'm aware it's not actually a struct, I just called it that. – leeand00 Jul 26 '17 at 16:12
  • You never set `myUno.model`, so it's still `None` from the class definition. – kindall Jul 26 '17 at 16:16
  • The `UnoObjs` class from [this github code](https://github.com/silnrsi/libreoffice-linguistic-tools/blob/master/LinguisticTools/pythonpath/lingt/utils/util.py) does this. – Jim K Jul 26 '17 at 16:43

2 Answers2

2

You need to be explicit:

   self.model = desktop.getCurrentComponent()

The model variable inside __init__ is local to that method, and won't be attached to the instance self unless you assign it.

When you defined model right under the class, but outside the __init__ method you defined a class attribute, which will be in all instances of that class.

Without that, when you accessed myUno.model you'd be facing an AttributeError.

Rafael Barros
  • 2,738
  • 1
  • 21
  • 28
2

I would add to the answer of Barros that you declare localContext = None, resolver = None, etc. as class variables. So the modified code is this (if you need all these variables as instance variables):

class UnoStruct():
    def __init__(self ):
        # get the uno component context from the PyUNO runtime
        self.localContext = uno.getComponentContext()

        # create the UnoUrlResolver
        self.resolver = localContext.ServiceManager.createInstanceWithContext("com.sun.star.bridge.UnoUrlResolver", localContext )

        # connect to the running office
        self.ctx = resolver.resolve( "uno:socket,host=localhost,port=2002;urp;StarOffice.ComponentContext" )
        self.smgr = ctx.ServiceManager

        # get the central desktop object
        self.desktop = smgr.createInstanceWithContext( "com.sun.star.frame.Desktop",ctx)

        # access the current writer document
        self.model = desktop.getCurrentComponent()
Kirill Bulygin
  • 3,658
  • 1
  • 17
  • 23
  • So `self` is like `this` in Java then? – leeand00 Jul 26 '17 at 20:41
  • 1
    @leeand00 Yes. The difference is that `self` is not a keyword (just a conventional name): you could substitute it by `obj`, `this`, whatever, since the parameter is explicit (this is pretty common for languages that were not designed as object-oriented initially). – Kirill Bulygin Jul 26 '17 at 22:16
  • right, cause it's an argument, so you can name it yourself. But if you want another Python coder to easily read it, it is best to stick to the `self` convention. – leeand00 Jul 26 '17 at 22:26