PyUsr
PyUsr

Reputation: 31

python + wx & uno to fill libreoffice using ubuntu 14.04

I collected user data using a wx python gui and than I used uno to fill this data into an openoffice document under ubuntu 10.xx

user + my-script ( +empty document ) --> prefilled document

After upgrading to ubuntu 14.04 uno doesn't work with python 2.7 anymore and now we have libreoffice instead of openoffice in ubuntu. when I try to run my python2.7 code, it says:

ImportError: No module named uno

How could I bring it back to work?

what I tried: installed https://pypi.python.org/pypi/unotools v0.3.3 sudo apt-get install libreoffice-script-provider-python

converted the code to python3 and got uno importable, but wx is not importable in python3 :-/

ImportError: No module named 'wx'

googled and read python3 only works with wx phoenix

so tried to install: http://wxpython.org/Phoenix/snapshot-builds/ but wasn't able to get it to run with python3

is there a way to get the uno bridge to work with py2.7 under ubuntu 14.04? Or how to get wx to run with py3? what else could I try?

Upvotes: 3

Views: 729

Answers (2)

Rolf of Saxony
Rolf of Saxony

Reputation: 22433

Create a python macro in LibreOffice that will do the work of inserting the data into LibreOffice and then in your python 2.7 code envoke the macro.
As the macro is running from with LibreOffice it will use python3. Here is an example of how to envoke a LibreOffice macro from the command line:

#!/usr/bin/python3
# -*- coding: utf-8 -*-
##
# a python script to run a libreoffice python macro externally
# NOTE: for this to run start libreoffice in the following manner
# soffice "--accept=socket,host=127.0.0.1,port=2002,tcpNoDelay=1;urp;" --writer --norestore
# OR
# nohup soffice "--accept=socket,host=127.0.0.1,port=2002,tcpNoDelay=1;urp;" --writer --norestore &
#
import uno
from com.sun.star.connection import NoConnectException
from com.sun.star.uno  import RuntimeException
from com.sun.star.uno  import Exception
from com.sun.star.lang import IllegalArgumentException
def uno_directmacro(*args):
    localContext = uno.getComponentContext()
    localsmgr = localContext.ServiceManager
    resolver = localsmgr.createInstanceWithContext("com.sun.star.bridge.UnoUrlResolver", localContext )
    try:
        ctx = resolver.resolve("uno:socket,host=localhost,port=2002;urp;StarOffice.ComponentContext")
    except NoConnectException as e:
        print ("LibreOffice is not running or not listening on the port given - ("+e.Message+")")
        return
    msp = ctx.getValueByName("/singletons/com.sun.star.script.provider.theMasterScriptProviderFactory")
    sp = msp.createScriptProvider("")
    scriptx = sp.getScript('vnd.sun.star.script:directmacro.py$directmacro?language=Python&location=user')
    try:
        scriptx.invoke((), (), ())
    except IllegalArgumentException as e:
        print ("The command given is invalid ( "+ e.Message+ ")")
        return
    except RuntimeException as e:
        print("An unknown error occurred: " + e.Message)
        return
    except Exception as e:
        print ("Script error ( "+ e.Message+ ")")
        print(e)
        return
    return(None)

uno_directmacro()

And this is the corresponding macro code within LibreOffice called "directmacro.py" and stored in the User area for libreOffice macros (which would normally be $HOME/.config/libreoffice/4/user/Scripts/python :

#!/usr/bin/python
from com.sun.star.awt.MessageBoxButtons import BUTTONS_OK, BUTTONS_OK_CANCEL, BUTTONS_YES_NO, BUTTONS_YES_NO_CANCEL, BUTTONS_RETRY_CANCEL, BUTTONS_ABORT_IGNORE_RETRY
from com.sun.star.awt.MessageBoxButtons import DEFAULT_BUTTON_OK, DEFAULT_BUTTON_CANCEL, DEFAULT_BUTTON_RETRY, DEFAULT_BUTTON_YES, DEFAULT_BUTTON_NO, DEFAULT_BUTTON_IGNORE
from com.sun.star.awt.MessageBoxType import MESSAGEBOX, INFOBOX, WARNINGBOX, ERRORBOX, QUERYBOX
def directmacro(*args):
    import socket, time
    class FontSlant():
        from com.sun.star.awt.FontSlant import (NONE, ITALIC,)
#get the doc from the scripting context which is made available to all scripts
    desktop = XSCRIPTCONTEXT.getDesktop()
    model = desktop.getCurrentComponent()
    text = model.Text
    tRange = text.End
    cursor = desktop.getCurrentComponent().getCurrentController().getViewCursor()
    doc = XSCRIPTCONTEXT.getDocument()
    parentwindow = doc.CurrentController.Frame.ContainerWindow

# your cannot insert simple text and text into a table with the same method
# so we have to know if we are in a table or not.
# oTable and oCurCell will be null if we are not in a table
    oTable = cursor.TextTable
    oCurCell = cursor.Cell
    insert_text = "This is text inserted into a LibreOffice Document\ndirectly from a macro called externally"
    Text_Italic = FontSlant.ITALIC
    Text_None = FontSlant.NONE
    cursor.CharPosture=Text_Italic
    if oCurCell == None: # Are we inserting into a table or not?
        text.insertString(cursor, insert_text, 0)
    else:
        cell = oTable.getCellByName(oCurCell.CellName)
        cell.insertString(cursor, insert_text, False)
    cursor.CharPosture=Text_None
    return None 

You will of course need to adapt the code to either accept data as arguments, read it from a file or whatever.

Upvotes: 1

Jim K
Jim K

Reputation: 13790

Ideally I would say use python 3, because python 2 is becoming outdated. The switch requires quite a bit of new coding changes, but better sooner than later. So I tried:

sudo pip3 install -U --pre \
    -f http://wxpython.org/Phoenix/snapshot-builds/ \
    wxPython_Phoenix

However this gave me errors, and I didn't want to spend the next couple of days working through them. Probably the pre-release versions are not ready for prime time yet.

So instead, what I recommend is to switch to AOO for now. See https://stackoverflow.com/a/27980255/5100564 for instructions. AOO does not have all the latest features that LO has, but it is a good solid Office product.

Apparently it is also possible to rebuild LibreOffice with python 2 using this script: https://gist.github.com/hbrunn/6f4a007a6ff7f75c0f8b

Upvotes: 0

Related Questions