Manipulating LibreOffice Documents with Python
Using Python to manipulate LibreOffice documents enables automated document generation, batch processing, data extraction, and formatting across LibreOffice Writer, Calc, and Impress. This automation is powered by the Python-UNO (PyUNO) bridge, a library that connects Python scripts directly to LibreOffice’s Universal Network Objects (UNO) API. Developers can execute these scripts either as internal macros directly within the LibreOffice user interface or as external standalone scripts communicating with a headless background instance of the software.
The PyUNO Interface
The core mechanism for automating LibreOffice is the uno
module, which comes bundled with standard LibreOffice installations. The
PyUNO bridge allows Python to interact with the underlying C++
components of LibreOffice, exposing objects such as the desktop manager,
document models, text cursors, and spreadsheet cell ranges.
Execution Methods
Python automation in LibreOffice generally follows one of two approaches:
- Embedded Macros: Scripts placed inside the user’s
LibreOffice scripts directory (
Scripts/python/) can be triggered via the LibreOffice GUI, assigned to hotkeys, or linked to document events. - Headless / External Automation: Standalone Python scripts connect to a running LibreOffice process over a local socket. This is ideal for server-side processing, automated report generation, and batch file conversion.
To run LibreOffice as a background service for external control, start it from the command line:
soffice --headless --accept="socket,host=localhost,port=2002;urp;StarOffice.ServiceManager"Basic Workflow for Document Manipulation
Manipulating any document through Python follows a standardized sequence of operations:
1. Connecting to the Instance
The script establishes a connection to the LibreOffice runtime environment via the local resolver:
import uno
from com.sun.star.beans import PropertyValue
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.ServiceManager")
desktop = context.ServiceManager.createInstanceWithContext(
"com.sun.star.frame.Desktop", context
)2. Opening or Creating a Document
Documents are opened using the loadComponentFromURL
method. Paths must be formatted as file URLs:
file_url = uno.systemPathToFileUrl("/path/to/document.odt")
document = desktop.loadComponentFromURL(file_url, "_blank", 0, ())To create a new document instead of opening an existing one, replace
the file URL with private:factory/swriter (for Writer) or
private:factory/scalc (for Calc).
3. Modifying Document Content
In Writer: Text can be inserted and formatted using the document’s
Textobject and cursors.text = document.Text cursor = text.createTextCursor() text.insertString(cursor, "Hello from Python!\n", False)In Calc: Cells and ranges are accessed via sheet objects.
sheets = document.getSheets() sheet = sheets.getByIndex(0) cell = sheet.getCellByPosition(0, 0) # Column A, Row 1 cell.setString("Automated Value")
4. Saving and Exporting
Changes can be saved directly back to the original file, saved to a new format, or exported as a PDF using filter properties:
pdf_filter = PropertyValue()
pdf_filter.Name = "FilterName"
pdf_filter.Value = "writer_pdf_Export"
output_url = uno.systemPathToFileUrl("/path/to/output.pdf")
document.storeToURL(output_url, (pdf_filter,))
document.dispose()Common Use Cases
- Batch Conversion: Rapidly converting
.docx,.odt,.xlsx, or.odsfiles to.pdfformat without manual interaction. - Mail Merge and Templating: Dynamically replacing placeholder tags in pre-designed templates with data pulled from databases or APIs.
- Spreadsheet Reporting: Generating structured financial and analytical reports by injecting data, calculating formulas, and applying styling via automated scripts.