Using Python scripting in Collabora Online

This document describes the Python scripting feature to manipulate documents being edited in Collabora Online.

Description

Python scripting allows for document manipulation while being edited in Collabora Online. The use-case assumes a web page has a Collabora Online document instance open in an iframe and that the functionality that wants to access the Python scripting is on the parts of the web page outside that iframe.

Background

The core LibreOffice has support for Python scripting already. Enhancements are made so that a Python script (or other code in the LibreOffice core) can return structured values to the JavaScript code in the browser, for instance lists, and not just simple strings or integers.

On the Online side, notifications from returning Python scripts are forwarded to the JavaScript code running in the browser.

Python script files

The Python script files containing functions to be called should be located in the LibreOffice installation, in the folder share/Scripts/python. (In the LibreOffice sources, they are in scripting/examples/python.) Currently, this folder contains Capitalise.py, HelloWorld.py, InsertText.py, NamedRanges.py, and SetSellColor.py and files that are used by the demo web page framed.html (see below), and a few others. Customer-specific Python files should be placed in the same location. After editing script files, the Collabora Online instance must be restarted.

These server-side scripts are read-only during run-time and cannot be modified via Online. Furthermore, the execution of Python scripting is limited to the Python script files in the aforementioned directory, which are prepared in advance. Arbitrary Python code execution is not possible, nor is the execution of dynamically code generated code. These are to guarantee strong security constraints.

Additional security is provided by not enabling the Python script provider by default. To enable it, you need to explicitly install, from the respective customer or CODE repositories, the following packages:

  • collaboraofficebasis-python-script-provider, makes it possible to implement uno “scripts” in python,

  • collaboraofficebasis-pyuno, makes it possible to implement uno components in python.

Instructions

In the Online sources there is a web page browser/html/framed.html and browser/html/framed.doc.html that are examples of web pages that run an unmodified Collabora Online instance inside an HTML iframe, and then from the HTML code outside the iframe calls Python scripts in the underlying LibreOffice instance to manipulate data in the document open in the Collabora Online instance. Various parameters can be passed to the Python scripts, and return values handled.

Both framed.html and framed.doc.html are just for demonstration purposes and very bare-bones visually.

Forms and JavaScript in framed.html and framed.doc.html

framed.html and framed.doc.html contain a set of small HTML forms and corresponding JavaScript functions that are invoked when a form is submitted. When a form is submitted, in this demonstration case, a corresponding JavaScript function is called. Of course in a real-life use case this could be constructed differently. The JavaScript function fetches the input fields and passes them to the JavaScript functionality of the Collabora Online running inside the iframe using the postMessage() standard JavaScript function.

The parameter to postMessage is a stringified JSON object. The interesting fields in that are: MessageId, which should be CallPythonScript, ScriptFile, which should be the file name of the Python source file containing the Python function to be called, Function which should be the name of the Python function to be called, and Values which should be a JSON object containing the (named) parameters to that Python function.

The JavaScript function receiveMessage() is set up to handle postMessage() events posted to the HTML page from the iframe, and handle especially those corresponding to return values from called Python functions. Those are distinguished by having a MessageId of CallPythonScript-Result.

Once receiveMessage() knows it is handling a return value from a Python script, it checks the commandName field which contains the LibreOffice vnd.sun.star.script URL of the called Python function. In the demonstration framed.html it is receiveMessage that then directly does what is necessary depending on the function called. In a more real-life use case, this could be done in some more generic and complex manner of course.

Sample Scripts

These scripts are provided as samples and as starting points for experimentation and further development. Users are encouraged to make copies of them and modify as necessary. Note that they may get overwritten when upgrading the Online packages, so making separate copies is highly recommended to avoid losing any changes.

SetCellColor:

The first form sets the colour of a cell in the (Calc) document open in the Collabora Online instance. The (zero-based) x and y coordinates of the cell, and the colour (in HTML format, like #A0FFA0 for a very light green) are input fields of the form. In this case the Python file is called SetCellColor.py, the function is called SetCellColor, and the parameters are the x and y coordinates and the colour.

GetNamedRanges:

The second form has no input fields and causes the function GetNamedRanges() in the Python file NamedRanges.py to be called. That function takes no parameter but returns a value that is a list of named ranges in the document. The receiveMessage() function inserts these into a textarea element.

AddNamedRange:

The third form is used to add a named range to the document. The input fields are as expected, the name and the range. The called Python function is AddNamedRange, also in NamedRanges.py. The JavaScript to call this is somewhat complicated because of different syntax used in the input fields and parameters passed to that Python function. One could as well put the parameter mangling into Python code, of course.

DeleteNamedRange:

Finally, and simplest sample, is a form to delete a named range.

InsertText:

This script demonstrates inserting a custom text into a Writer document, replacing any selection (if exists), otherwise inserting at the cursor’s position.