自动化的“公式”在Libreoffice通过Uno在Python

发布于 2025-02-06 02:04:40 字数 2127 浏览 2 评论 0原文

我经常从外部来源(通过Google文档)收到电子表格,必须转换为本地(专有)格式。为此,我编写了一个可以将电子表格作为ODS文件转换为所需格式(非ods)的脚本。 该脚本需要与许多高级业务特定的PHP东西进行交互,因此我将phpspreadsheet用于此目的( https://github.com/phpoffice/phpspreadsheet/ )。

从理论上讲,这个PHP库可以完成我需要的所有内容,但是它无法处理过度复杂的电子表格,而无需花费大量时间处理所有交叉引用公式。为了加快脚本中的处理,我通过将所有公式转换为值(选择所需纸张中的所有单元格,然后触发[data]> [计算]> [公式]将所有公式手动准备ODS文件))))在所需的床单中。然后,我删除所有不需要的床单(否则仅包含替换配方的源数据)。结果文件小得多,不包含任何公式。通过简化的电子表格文件,PHP脚本的执行在几秒钟内完成,而原始电子表格文件很长一段时间后将其耗尽。

我现在寻求使用新的Python脚本将所有公式转换为值的过程自动化(这需要在Linux服务器上发生,因此我最好的选择是通过Python的UNO插座控制的无头libreoffice,正确吗?)。 到目前为止Star/Sheet/Module-ix.html“ RER =“ Nofollow Noreferrer”> https://www.openoffice.org/api/pi/docs/common/common/ref/ref/ref/sun/sun/sun/sun/sun/sheet/sheet/mmodule-module-ix.html )。 我目前的大问题是:

如何通过python中的uno api立即访问表格上的所有单元格上的ui- 函数?

我尝试过在搜索旧的OpenOffice API文档中为此暂时,但是到目前为止,我还找不到我想要的东西。

目前,Python脚本(本质上)看起来像这样:

import uno

localContext = uno.getComponentContext()

resolver = localContext.ServiceManager.createInstanceWithContext(
    "com.sun.star.bridge.UnoUrlResolver", 
    localContext 
)

context = resolver.resolve("uno:socket,host=localhost,port=2002;urp;StarOffice.ComponentContext")

serviceManager = context.ServiceManager

desktop = serviceManager.createInstanceWithContext("com.sun.star.frame.Desktop", context)

# com.sun.star.lang.XComponent / com.sun.star.sheet.SpreadsheetDocument
document = desktop.getCurrentComponent()

# com.sun.star.sheet.XSpreadsheets / XNameAccess
sheets = document.getSheets()

# com.sun.star.sheet.XSpreadsheet   
# https://www.openoffice.org/api/docs/common/ref/com/sun/star/sheet/XSpreadsheet.html
sheet = sheets.getByName('OneOfTheSheets')

#print(sheet.getCellRangeByName("A1:AP1000"))

# WAY TOO SLOW AND DESTRUCTIVE:
for row in range(0, 1000):
    for column in range(0, 42):
        cell = sheet.getCellByPosition(column, row)
        cell.setFormula(cell.getString())

谢谢您提供的任何帮助。

I am regularly receiving a spreadsheet from an external source (via google docs) that I have to convert into a local (kinda proprietary) format. To do that, I have written a script that can convert the spreadsheet as an ODS file into the needed format (non-ODS).
This script needs to interact with a lot of higher-level business-specific PHP stuff, so I use PhpSpreadsheet for this purpose (https://github.com/PHPOffice/PhpSpreadsheet/).

This PHP library does theoretically everything I need, but it cannot deal with overly complex spreadsheets without taking an gigantic amount of time dealing with all the cross-referencing formulas. To speed up the processing in the script, I manually prepare the ODS file by hand by converting all formulas to values (Select all Cells in the needed Sheets, then trigger [Data] > [Calculate] > [Formula to Value]) in the needed sheets. Then I delete all the unneeded sheets (which otherwise only contain source-data for the replaced formulas). The resulting file is a lot smaller and does not contain any formulas. The execution of the PHP script finishes within a few seconds with the simplified spreadsheet file, while it runs out of memory after a long while with the original spreadsheet file.

I now seek to automate this process of converting all the formulas to values using a new python script (This needs to happen on a linux server, so my best bet would be a headless libreoffice controlled via an UNO socket in python, correct?).
So far I have managed to connect to the libreoffice UNO socket and manipulate the cells via the old OpenOffice-API (https://www.openoffice.org/api/docs/common/ref/com/sun/star/sheet/module-ix.html).
My current big question is:

How do I access the UI-Formula to Value-functionality on all cells of a sheet at once via the UNO API in Python?

I have tried searching the old OpenOffice API documentation for this for a while, but so far I cannot find what I am looking for.

Currently the python script looks (in essence) like this:

import uno

localContext = uno.getComponentContext()

resolver = localContext.ServiceManager.createInstanceWithContext(
    "com.sun.star.bridge.UnoUrlResolver", 
    localContext 
)

context = resolver.resolve("uno:socket,host=localhost,port=2002;urp;StarOffice.ComponentContext")

serviceManager = context.ServiceManager

desktop = serviceManager.createInstanceWithContext("com.sun.star.frame.Desktop", context)

# com.sun.star.lang.XComponent / com.sun.star.sheet.SpreadsheetDocument
document = desktop.getCurrentComponent()

# com.sun.star.sheet.XSpreadsheets / XNameAccess
sheets = document.getSheets()

# com.sun.star.sheet.XSpreadsheet   
# https://www.openoffice.org/api/docs/common/ref/com/sun/star/sheet/XSpreadsheet.html
sheet = sheets.getByName('OneOfTheSheets')

#print(sheet.getCellRangeByName("A1:AP1000"))

# WAY TOO SLOW AND DESTRUCTIVE:
for row in range(0, 1000):
    for column in range(0, 42):
        cell = sheet.getCellByPosition(column, row)
        cell.setFormula(cell.getString())

Thank you for any help you can provide.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文