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:

  1. 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.
  2. 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

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