杰瑞科技汇

Python如何调用LibreOffice?

Of course! Using Python with LibreOffice is a powerful way to automate tasks, create custom reports, and extend the functionality of LibreOffice. The primary method for this is through UNO (Universal Network Objects), which is the component model used by LibreOffice and its sibling, OpenOffice.

Python如何调用LibreOffice?-图1
(图片来源网络,侵删)

Here's a comprehensive guide covering the concepts, setup, and practical examples.


What is UNO?

Think of UNO as the "nervous system" of LibreOffice. It's a programming language-neutral interface that allows different applications to communicate with each other and control each other's objects. When you use Python to control LibreOffice, you are using Python to send UNO commands to the LibreOffice process.

The Two Main Approaches

There are two primary ways to use Python with LibreOffice:

  1. External Script (Most Common & Recommended): You write a Python script on your computer (e.g., my_script.py). This script starts a hidden LibreOffice process in the background, connects to it via UNO, performs actions, and then closes LibreOffice. This is great for automation tasks like batch processing documents.
  2. Macros (Embedded in the Document): You write Python code directly inside a LibreOffice document (.ods, .odt, etc.) as a macro. This code runs when the user triggers it (e.g., via a button or a menu item). This is ideal for adding interactive features to a specific document.

We will focus on the External Script approach as it's more versatile for automation.

Python如何调用LibreOffice?-图2
(图片来源网络,侵删)

Setup: Prerequisites

You need two things installed:

  1. Python: A standard Python installation on your system.
  2. LibreOffice: A full installation of LibreOffice. The "portable" versions might not work correctly for this.

The Crucial Part: The uno Package

The uno package is not a standard Python package you install with pip. It's bundled with your LibreOffice installation. Your Python script needs to be able to find it.

How to find the path: The uno module is located in a subdirectory of your LibreOffice installation. The path looks something like this:

  • Windows: C:\Program Files\LibreOffice\program\python-core-3.8\lib\python3.8
  • Linux: /usr/lib/libreoffice/program/python-core-3.8/lib/python3.8
  • macOS: /Applications/LibreOffice.app/Contents/Resources/program/python-core-3.8/lib/python3.8

You need to add this path to your PYTHONPATH environment variable so Python can find it.

Python如何调用LibreOffice?-图3
(图片来源网络,侵删)

Example 1: Creating a New Spreadsheet and Writing Data

This is the "Hello, World!" of LibreOffice automation. It will start LibreOffice, create a new Calc (spreadsheet) document, write some data into cells, and save the file.

Step 1: Create the Python Script (create_spreadsheet.py)

import os
import uno
import unohelper
# --- Configuration ---
# IMPORTANT: Change this path to your LibreOffice installation
# The path should point to the 'python-core-...' directory.
LO_PYTHON_PATH = r"C:\Program Files\LibreOffice\program\python-core-3.8\lib\python3.8"
# Path to the soffice executable (the main LibreOffice program)
SOFFICE_EXECUTABLE = r"C:\Program Files\LibreOffice\program\soffice.exe"
# Output file path
OUTPUT_FILE = r"C:\path\to\your\output\my_new_spreadsheet.ods"
def main():
    # Add the LibreOffice Python path to sys.path
    # This allows Python to import the 'uno' module
    import sys
    if LO_PYTHON_PATH not in sys.path:
        sys.path.insert(0, LO_PYTHON_PATH)
    # Now we can import the uno module
    import uno
    # Start the LibreOffice headless process
    # The 'headless' part means no GUI will be shown.
    # 'accept' is a security setting that allows the script to connect.
    # 'norestore' prevents LibreOffice from restoring previous sessions.
    # 'pipe' is a connection method.
    command = [
        SOFFICE_EXECUTABLE,
        "--headless",
        "--accept=socket,host=localhost,port=2002;urp;StarOffice.ServiceManager",
        "--norestore"
    ]
    # Start the process in the background
    import subprocess
    subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    # Connect to the running LibreOffice instance
    local_context = uno.getComponentContext()
    resolver = local_context.ServiceManager.createInstanceWithContext(
        "com.sun.star.bridge.UnoUrlResolver", local_context
    )
    # This is the connection string. It might take a few seconds to connect.
    context = resolver.resolve("uno:socket,host=localhost,port=2002;urp;StarOffice.ServiceManager")
    desktop = context.ServiceManager.createInstanceWithContext("com.sun.star.frame.Desktop", context)
    # Create a new spreadsheet document
    # 'com.sun.star.sheet.SpreadsheetDocument' is the type for Calc
    doc = desktop.loadComponentFromURL("private:factory/scalc", "_blank", 0, ())
    # Get the first sheet
    sheets = doc.getSheets()
    sheet = sheets.getByIndex(0)
    sheet.setName("Sales Data")
    # Write data to cells
    # Cell addressing is 0-based
    sheet.getCellByPosition(0, 0).setString("Product")
    sheet.getCellByPosition(1, 0).setString("Q1 Sales")
    sheet.getCellByPosition(0, 1).setString("Laptop")
    sheet.getCellByPosition(1, 1).setString("150")
    sheet.getCellByPosition(0, 2).setString("Mouse")
    sheet.getCellByPosition(1, 2).setString("250")
    # Save the document
    # The URL must be in file:/// format
    save_url = uno.systemPathToFileUrl(OUTPUT_FILE)
    doc.storeToURL(save_url, ())
    # Close the document without saving changes again (storeToURL already did)
    doc.close(True)
    print(f"Spreadsheet created successfully at: {OUTPUT_FILE}")
if __name__ == "__main__":
    main()

Step 2: Run the Script

  1. Modify the paths in the script (LO_PYTHON_PATH, SOFFICE_EXECUTABLE, OUTPUT_FILE) to match your system.
  2. Open your command prompt or terminal.
  3. Navigate to the directory where you saved create_spreadsheet.py.
  4. Run the script:
    python create_spreadsheet.py

You should see a new file named my_new_spreadsheet.ods appear at the specified location.


Example 2: Reading Data from an Existing Spreadsheet

This script will open an existing spreadsheet, read data from a specific cell, and print it to the console.

Step 1: Create the Python Script (read_spreadsheet.py)

import os
import uno
import unohelper
import subprocess
# --- Configuration ---
LO_PYTHON_PATH = r"C:\Program Files\LibreOffice\program\python-core-3.8\lib\python3.8"
SOFFICE_EXECUTABLE = r"C:\Program Files\LibreOffice\program\soffice.exe"
INPUT_FILE = r"C:\path\to\your\output\my_new_spreadsheet.ods" # Use the file from the previous example
def main():
    # Setup PYTHONPATH
    import sys
    if LO_PYTHON_PATH not in sys.path:
        sys.path.insert(0, LO_PYTHON_PATH)
    # Start LibreOffice headless process
    command = [
        SOFFICE_EXECUTABLE,
        "--headless",
        "--accept=socket,host=localhost,port=2002;urp;StarOffice.ServiceManager",
        "--norestore"
    ]
    subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    # Connect to LibreOffice
    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)
    # Open the existing document
    file_url = uno.systemPathToFileUrl(INPUT_FILE)
    doc = desktop.loadComponentFromURL(file_url, "_blank", 0, ())
    # Get the first sheet
    sheet = doc.getSheets().getByIndex(0)
    # Read data from cell B2 (which is at position 1, 1)
    cell_value = sheet.getCellByPosition(1, 1).getString()
    print(f"The value in cell B2 is: {cell_value}")
    # Close the document
    doc.close(True)
    print("Script finished.")
if __name__ == "__main__":
    main()

Step 2: Run the Script

python read_spreadsheet.py

Expected Output:

The value in cell B2 is: 150
Script finished.

Important Considerations and Best Practices

  • Performance: Starting LibreOffice for every script is slow. For batch processing, it's much more efficient to start LibreOffice once in a persistent headless mode and have your script connect to it. You can even run a LibreOffice instance as a service.
  • Error Handling: Always wrap your UNO calls in try...except blocks. If LibreOffice isn't running or the path is wrong, your script will fail with a com.sun.star.connection.NoConnectException or similar.
  • Documentation: The best documentation for UNO is the API reference itself. It can be dense, but it's the ultimate source of truth.
    • LibreOffice API Documentation: https://api.libreoffice.org/
    • Search for services like com.sun.star.sheet.SpreadsheetDocument, com.sun.star.table.CellRange, etc.
  • LibreOffice Basic: You can also record macros in LibreOffice using its built-in Basic language. This is a great way to learn the UNO object names and methods. You can then translate the recorded Basic code into Python.

Advanced Topic: Using Python Macros (Embedded)

To run Python code inside a LibreOffice document:

  1. Enable Python Macros:
    • Go to Tools -> Options -> LibreOffice -> Advanced.
    • Check the box for Enable macros support.
    • Select Show security warning for macros or Confirm opening macros.
  2. Create a Python Module:
    • Go to Tools -> Macros -> Organize Python Macros -> LibreOffice Basic....
    • This opens the Macro Organizer. In the "Python" tab, you can create a new library and module.
    • Give your module a name, e.g., MyDocumentMacros.
  3. Write the Code:
    • The IDE will open. You can now write your Python code. The global XSCRIPTCONTEXT variable is automatically provided, which gives you access to the document, desktop, etc.

Example Embedded Macro Code:

# This code would be inside your MyDocumentMacros.py module
def hello_world_macro():
    """
    This is a simple macro that creates a message box.
    """
    doc = XSCRIPTCONTEXT.getDocument()
    desktop = XSCRIPTCONTEXT.getDesktop()
    # Get the first sheet of the current document
    sheet = doc.getSheets().getByIndex(0)
    sheet.getCellByPosition(0, 4).setString("Hello from a Python Macro!")
    # Create a message box
    toolkit = desktop.getToolkit()
    msgbox = toolkit.createMessageBox(
        doc.getCurrentController().getFrame(),
        "com.sun.star.awt.MessageBoxType.INFO",
        1,
        "Python Macro",
        "The macro has run successfully!"
    )
    msgbox.execute()
# This line makes the function callable from LibreOffice's macro dialog
g_exportedScripts = hello_world_macro,

After saving this, you can run it from Tools -> Macros -> Run Macro....

分享:
扫描分享到社交APP
上一篇
下一篇