Of course! Here is a comprehensive guide to using Python with LibreOffice, covering the official UNO bindings, the popular pyuno bridge, and a practical example.
What is UNO?
UNO (Universal Network Objects) is the core component and API (Application Programming Interface) of LibreOffice (and OpenOffice). It's a cross-platform component model that allows different parts of the office suite (like the Writer word processor, Calc spreadsheet, and Base database) to communicate with each other and, most importantly, with external programs like Python.
Think of UNO as the language that LibreOffice speaks. To control it from Python, you need a way to speak that language. This is where the Python-UNO bridge comes in.
The Two Main Ways to Use Python with LibreOffice
There are two primary methods to interact with LibreOffice from Python:
- The Official UNO Bindings (Recommended for most users): This is the most straightforward and modern method. LibreOffice itself includes a Python interpreter and the necessary UNO libraries. You run your script directly from within LibreOffice.
- The
pyunoBridge (For external control): This method allows you to run a Python script outside of LibreOffice that can connect to and control a running LibreOffice instance. It's more complex to set up.
Method 1: Using the Official UNO Bindings (In-Process)
This is the easiest way to get started. You write a Python script and run it using a special command-line tool provided by LibreOffice.
Step 1: Write Your Python Script
Create a Python file, for example, hello_writer.py. This script will create a new Writer document, add some text, and save it.
# hello_writer.py
import uno
# Get the Uno components context from the PyUNO runtime
local_context = uno.getComponentContext()
# Create the Uno service manager
resolver = local_context.ServiceManager.createInstanceWithContext(
"com.sun.star.bridge.UnoUrlResolver", local_context
)
# Connect to the running office
# The "uno:socket,host=localhost,port=2002;urp;StarOffice.ComponentContext" is the standard URL.
# We use a try-except block to handle cases where LibreOffice isn't running in "listen" mode.
try:
context = resolver.resolve("uno:socket,host=localhost,port=2002;urp;StarOffice.ComponentContext")
except Exception as e:
print("Error connecting to LibreOffice. Make sure it is running with the 'pyuno' server option.")
print(f"Details: {e}")
exit()
# Get the desktop service (the main window)
desktop = xDesktop = context.ServiceManager.createInstance("com.sun.star.frame.Desktop")
# Create a new text document
document = desktop.loadComponentFromURL(
"private:factory/swriter", "_blank", 0, ()
)
# Get the text from the document's text cursor
text = document.getText()
cursor = text.createTextCursor()
# Insert some text
text.insertString(cursor, "Hello from Python!", 0)
# Save the document
# The URL uses the internal 'private:' protocol for saving to the user's home directory.
# You can also use a file system path like 'file:///home/user/mydocument.odt'
file_url = "private:hello_from_python.odt"
props = (
# A tuple of property name-value pairs
("FilterName", "writer8"), # Specify the filter (e.g., 'writer8' for .odt)
)
document.storeToURL(file_url, props)
# Close the document
document.close(True)
print("Document created and saved successfully!")
Step 2: Run LibreOffice in "Server" Mode
Before you can run the script, you need to start LibreOffice and tell it to listen for external Python connections. Open a terminal or command prompt and run:
soffice --accept="socket,host=localhost,port=2002;urp;StarOffice.ServiceManager"
soffice: The command to start LibreOffice (it might belibreofficeorsofficedepending on your system).--accept: This is the key flag that tells LibreOffice to act as a server.socket,host=localhost,port=2002: It will listen for connections on your local machine at port 2002.
Leave this terminal window open. LibreOffice will start, but you might not see a main window appear immediately (or it might appear briefly). It's now running in the background, waiting for your script.
Step 3: Run Your Python Script
Now, open a new terminal window and run your Python script. The key is to use the python executable that comes with LibreOffice, as it has the UNO libraries pre-loaded.
# The path to the python interpreter inside the LibreOffice installation # This path varies by operating system! # On Linux: it's often in /usr/lib/libreoffice/program/ # On Windows: it's often in "C:\Program Files\LibreOffice\program\python.exe" # On macOS: it's often in /Applications/LibreOffice.app/Contents/MacOS/python # Example for Linux: /usr/lib/libreoffice/program/python hello_writer.py
If everything is set up correctly, your script will execute, and a new LibreOffice Writer document named hello_from_python.odt will be saved in your user's home directory.
Method 2: Using the pyuno Bridge (External Control)
This method allows you to use your system's standard Python installation. It's more complex because you have to manually set up the PYTHONPATH.
Step 1: Install pyuno (Linux)
On Debian/Ubuntu-based systems, you can install it with a package manager:
sudo apt-get install python3-pyuno
This will set up the necessary links and environment variables for you.
Step 2: Set Up Environment Variables (Manually if needed)
If pyuno isn't available as a package, you need to set the PYTHONPATH manually so your Python interpreter can find the UNO libraries.
-
Find the LibreOffice installation directory. Let's call it
LIBREOFFICE_HOME. -
Add the following directories to your
PYTHONPATHenvironment variable:LIBREOFFICE_HOME/program(containsunorcand other base files)LIBREOFFICE_HOME/program/python-core-3.x(contains the Python interpreter and standard library)LIBREOFFICE_HOME/program/pythonloader(contains the UNO loader for Python)
Example for Linux/Bash:
export PYTHONPATH="/usr/lib/libreoffice/program:/usr/lib/libreoffice/program/python-core-3.8:/usr/lib/libreoffice/program/pythonloader:${PYTHONPATH}"
Step 3: Run LibreOffice in "Server" Mode
This is the exact same command as in Method 1.
soffice --accept="socket,host=localhost,port=2002;urp;StarOffice.ServiceManager"
Step 4: Run Your Script with Your System's Python
Now you can run your script using the standard python or python3 command.
python3 hello_writer.py
Practical Example: Manipulating a Calc Spreadsheet
Here’s a more advanced example that reads data from a Python list and writes it into a LibreOffice Calc spreadsheet.
# manipulate_calc.py
import uno
import time
# --- Connection part (same as before) ---
try:
local_context = uno.getComponentContext()
resolver = local_context.ServiceManager.createInstanceWithContext(
"com.sun.star.bridge.UnoUrlResolver", local_context
)
context = resolver.resolve("uno:socket,host=localhost,port=2002;urp;StarOffice.ComponentContext")
desktop = context.ServiceManager.createInstance("com.sun.star.frame.Desktop")
except Exception as e:
print("Error connecting to LibreOffice.")
print(f"Details: {e}")
exit()
# --- Data to be written ---
data = [
["Product", "Sales Q1", "Sales Q2", "Sales Q3", "Sales Q4"],
["Laptops", 150, 180, 210, 250],
["Monitors", 90, 110, 125, 140],
["Keyboards", 200, 220, 240, 260],
]
# Create a new spreadsheet document
document = desktop.loadComponentFromURL(
"private:factory/scalc", "_blank", 0, ()
)
# Get the first sheet
sheet = document.getSheets().getByIndex(0)
# Get the cell cursor
cell_cursor = sheet.createCursor()
# Loop through the data and write it to the sheet
for row_index, row_data in enumerate(data):
for col_index, cell_value in enumerate(row_data):
cell = sheet.getCellByPosition(col_index, row_index)
cell.setString(str(cell_value))
# Auto-fit the columns for better readability
columns = sheet.getColumns()
for i in range(len(data[0])):
columns.getByIndex(i).setIsAutomaticHeight(True)
columns.getByIndex(i).setOptimalWidth(True)
# Save and close
file_url = "private:/sales_report.ods"
document.storeToURL(file_url, ())
document.close(True)
print("Sales report created successfully!")
You would run this script the same way as the previous one, while LibreOffice is listening in the other terminal.
Key UNO Concepts to Remember
- Service Manager (
context.ServiceManager): The factory for creating all other UNO objects. - Desktop (
com.sun.star.frame.Desktop): The root object that manages all open documents. - Component (
com.sun.star.text.TextDocument,com.sun.star.sheet.SpreadsheetDocument): Represents a document. - Cursor (
com.sun.star.text.TextCursor,com.sun.star.table.CellCursor): Used to navigate and select content within a document. - Properties (
PropertyValuetuple): Used to pass named parameters to methods, like when saving a file with a specific filter.
Debugging Tips
- Check the Connection: The most common error is
Error connecting to LibreOffice. Double-check that you ran thesoffice --accept...command and that it's still running. - Use the Right Python: Make sure you are using the Python interpreter that comes with LibreOffice when using the official bindings.
- Read the UNO API Documentation: The ultimate source of truth is the LibreOffice API Documentation. It lists all available services, interfaces, and properties.
