To operate LibreOffice with Python
There are three methods.
The first method requires GUI operation, so batch processing from the program cannot be performed. The operator responds to any errors.
The second method can be used for batch processing because LibreOffice will be closed after the macro is finished. When an error occurs, LibreOffice displays a dialog and waits, and the program cannot handle it. Considering possible errors, it is necessary to take measures such as setting a time limit in timeout-decorator. Also, if there is LibreOffice that has already been started when LibreOffice is started, processing will be performed there, so it may not be possible to control as expected.
The third method is to specify the --accept switch to LibreOffice in advance so that it can be connected with a socket or a named pipe and start it. With this method, if LibreOffice is started first, the process will be performed there, so it may not be possible to control as expected. I could use it on Microsoft Windows, but on FreeBSD I get an error when connecting and cannot run it.
Microsoft Windows
In Microsoft Windows, LibreOffice comes with a Python processor% PROGRAMFILES% \ LibreOffice \ program \ python.exe, which is automatically used for macros. Even when connecting from the command line, it is necessary to use the Python processing system that comes with LibreOffice. The Python version that comes with LibreOffice 6.3.6 is 3.5.9.
The library is installed in% PROGRAMFILES% \ LibreOffice \ program \ python-core-3.5.9 \ lib. There is also a site-packages subfolder, which goes through sys.path, but only has a README file. Package installation is not easy due to lack of pip. From Installation of pip site You can install it by downloading and running get-pip.py, but if you run it with personal account privileges % PROGRAMFILES% \ LibreOffice \ program \ python-core-3.5.9 \ lib \ site-packages is not writable It is installed in% APPDATA% \ Roaming \ Python \ Python35 \ site-packages under the user's profile.
C:\Users\shota243>cd Downloads
C:\Users\shota243\Downloads>"c:\Program Files\LibreOffice\program"\python get-pip.py
Defaulting to user installation because normal site-packages is not writeable
Collecting pip
Downloading pip-20.1.1-py2.py3-none-any.whl (1.5 MB)
|################################| 1.5 MB 1.3 MB/s
Collecting setuptools
Downloading setuptools-47.1.1-py3-none-any.whl (583 kB)
|################################| 583 kB 6.8 MB/s
Collecting wheel
Downloading wheel-0.34.2-py2.py3-none-any.whl (26 kB)
Installing collected packages: pip, setuptools, wheel
WARNING: The scripts pip.exe, pip3.5.exe and pip3.exe are installed in 'C:\Users\shota243\AppData\Roaming\Python\Python35\Scripts' which is not on PATH.
Consider adding this directory to PATH or, if you prefer to suppress this warning, use --no-warn-script-location.
WARNING: The scripts easy_install-3.5.exe and easy_install.exe are installed in 'C:\Users\shota243\AppData\Roaming\Python\Python35\Scripts' which is not on PATH.
Consider adding this directory to PATH or, if you prefer to suppress this warning, use --no-warn-script-location.
WARNING: The script wheel.exe is installed in 'C:\Users\shota243\AppData\Roaming\Python\Python35\Scripts' which is not on PATH.
Consider adding this directory to PATH or, if you prefer to suppress this warning, use --no-warn-script-location.
Successfully installed pip-20.1.1 setuptools-47.1.1 wheel-0.34.2
pip.exe is also installed in% APPDATA% \ Roaming \ Python \ Python35 \ Scripts, but you have to set it yourself to put this folder in the PATH and% PROGRAMFILES% to run pip.exe Considering that \ LibreOffice \ program \ python35.dll is required, it is also necessary to deal with the DLL search path.
%PROGRAMFILES%\LibreOffice\program\python -m pip
It may be easier to start with. Packages installed with pip are also installed in% APPDATA% \ Roaming \ Python \ Python35 \ site-packages, but they can be used as they are because sys.path is available.
C:\Users\shota243>"c:\Program Files\LibreOffice\program"\python -m pip install timeout-decorator
Defaulting to user installation because normal site-packages is not writeable
Collecting timeout-decorator
Downloading timeout-decorator-0.4.1.tar.gz (4.8 kB)
Building wheels for collected packages: timeout-decorator
Building wheel for timeout-decorator (setup.py) ... done
Created wheel for timeout-decorator: filename=timeout_decorator-0.4.1-py3-none-any.whl size=5022 sha256=5d3ecc37c619ed429c313b18ddf3b01b309d43dccc65d19ce974df
76af478609
Stored in directory: c:\users\shota243\appdata\local\pip\cache\wheels\df\f4\3c\031226c90008861114781e36ef5898934aad3196808c40e6ea
Successfully built timeout-decorator
Installing collected packages: timeout-decorator
Successfully installed timeout-decorator-0.4.1
If you run get-pip.py with administrator privileges, you can install pip in a folder under% PROGRAMFILES% and share it on your system. Other packages can be installed under% PROGRAMFILES% as well. However, the% PROGRAMFILES% \ LibreOffice folder may be deleted when LibreOffice is updated, and it may be necessary to take action.
FreeBSD
In the case of FreeBSD, even if LibreOffice does not come with a Python processing system and it is a macro, Python that is in the PATH is used. Packages installed with pip can also be used from macros. If you start LibreOffice in a virtual environment, you can use different Python versions and packages.
UNO
Use UNO (Universal Network Objects) to operate LibreOffice programmatically. UNO is a language-independent component model that uses Python-UNO bridge (PyUNO-bridge) when used from Python. .. Use the Python-UNO bridge as well, whether from a macro or an external connection.
LibreOffice has neither the ability to edit Python macros nor the ability to launch editors. Create a Python macro separately and place it in the following directory.
--User macro
%APPDATA%\LibreOffice\4\user\Scripts\python
--System shared macro
%PROGRAMFILES%\LibreOffice\share\Scripts\python
--User macro
${HOME}/.config/libreoffice/4/user/Scripts/python
--System shared macro
/usr/local/lib/libreoffice/share/Scripts/python
The directory for user macro placement does not exist from the beginning, so create it yourself if necessary.
APSO --Alternative Script Organizer for Python After installing the extension, you can:
--Launch Python interpreter console --Using the GUI Debugger --Launch the editor from LibreOffice and edit the macro --Embedding Python macros in documents
This makes it possible to edit without being aware of the macro layout. You can also try accessing the UNO from the Python interpreter.
XSCRIPTCONTEXT global variables can be referenced from Python macros. From XSCRIPTCONTEXT, you can access the environment where the macro is started by the following method.
XSCRIPTCONTEXT is an implementation of the XScriptContext interface, As a global variable of Python, it is an instance of the pythonscript.ScriptContext class.
>>> type(XSCRIPTCONTEXT)
<class 'pythonscript.ScriptContext'>
The class definition is in the /usr/local/lib/libreoffice/program/pythonscript.py file.
The command line to specify macros when starting LibreOffice is as follows
soffice 'vnd.sun.star.script:<Script file name>$<Function name>?language=Python&location=user'
This will run the macro and exit LibreOffice. If the macro doesn't need to show the screen, turn on the --headless switch and the screen won't show. If an error occurs during macro execution, an error dialog will be displayed to request user confirmation, but if --headless is specified, the dialog will not be displayed and the hang will occur.
Example:
mymacro.py
def macrofunc():
pass
To start without screen display
$ soffice --headless 'vnd.sun.star.script:mymacro.py$macrofunc?language=Python&location=user'
To receive an external connection, specify the --accept switch in LibreOffice in advance and start it. For socket connection
$ soffice "--accept=socket,host=<Host designation>,port=<port number>;urp;"
For named pipe connection
$ soffice "--accept=pipe,name=<Named pipe name>;urp;"
In both cases, UNIX-like OS shells treat semicolons (;) as command delimiters, so they need to be quoted.
Example:
$ soffice --writer "--accept=socket,host=0,port=2002;urp;"
$ soffice --calc --headless "--accept=pipe,name=librepipe;urp;"
In the example page Python-UNO bridge
"-accept=socket,host=localhost,port=2002;urp;"
And the "accept" has a single minus sign, which is the old notation and the current notation is to write two. Also, in the same example, the program inserts the "Hello, World" character string into the Writer document, but since the document is not newly created in the program, if it is executed as it is, an error will occur when accessing the text property. If you create a new document with the --writer switch when you start LibreOffice, that document will be used.
In the Python program, the parameter of the --accept option switch when LibreOffice is started is specified when the resolver (com.sun.star.bridge.UnoUrlResolver instance) resolves the connection destination on the side connecting the same character string. Since host is the partner host name, different values will be specified.
Once you connect to LibreOffice and get the Context, you can use it to create a Desktop instance and an instance of the ScriptContext class to replace the XSCRIPTCONTEXT global variable in your macro. The third argument of the constructor of the ScriptContext class is the invocation context, but it can be NULL according to the XScriptContext Interface Documentation. Specify None.
import uno
from pythonscript import ScriptContext
def connect_script_context(host='localhost', port='2002', namedpipe=None):
UNO_RESOLVER = "com.sun.star.bridge.UnoUrlResolver"
UNO_DESKTOP = "com.sun.star.frame.Desktop"
localCtx = uno.getComponentContext()
localSmgr = localCtx.ServiceManager
resolver = localSmgr.createInstanceWithContext(UNO_RESOLVER, localCtx)
if namedpipe is None:
uno_string = 'uno:socket,host=%s,port=%s;urp;StarOffice.ComponentContext' % (host, port)
else:
uno_string = 'uno:pipe,name=%s;urp;StarOffice.ComponentContext' % namedpipe
ctx = resolver.resolve(uno_string)
smgr = ctx.ServiceManager
XSCRIPTCONTEXT = ScriptContext(ctx,
smgr.createInstanceWithContext(UNO_DESKTOP, ctx),
None)
return XSCRIPTCONTEXT
Simulate the case of a macro by assigning the return value of this connect_script_context () function to the XSCRIPTCONTEXT global variable.
When connecting to LibreOffice from FreeBSD or a UNIX-like system, the Python program under / usr / local / lib / libreoffice / program is imported and the dynamic link library in the same location is also used, so LD_LIBRARY_PATH is used in addition to PYTHONPATH. Also pass environment variables.
export PYTHONPATH="${PYTHONPATH}:/usr/local/lib/libreoffice/program"
export LD_LIBRARY_PATH="${LD_LIBRARY_PATH}:/usr/local/lib/libreoffice/program"
export PATH="${PATH}:/usr/local/lib/libreoffice/program"
When I actually connect, I can connect and get the ComponentContext, but I get an error when I try to get the Desktop.
>>> import uno
import uno
>>> localContext = uno.getComponentContext()
localContext = uno.getComponentContext()
>>> resolver = localContext.ServiceManager.createInstanceWithContext("com.sun.star.bridge.UnoUrlResolver", localContext)
<reateInstanceWithContext("com.sun.star.bridge.UnoUrlResolver", localContext)
>>> ctx = resolver.resolve("uno:socket,host=localhost,port=2002;urp;StarOffice.ComponentContext")
ctx = resolver.resolve("uno:socket,host=localhost,port=2002;urp;StarOffice.ComponentContext")
>>> smgr = ctx.ServiceManager
smgr = ctx.ServiceManager
>>> desktop = smgr.createInstanceWithContext("com.sun.star.frame.Desktop",ctx)
desktop = smgr.createInstanceWithContext("com.sun.star.frame.Desktop",ctx)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
__main__.RuntimeException: Binary URP bridge disposed during call
Recommended Posts