简体   繁体   English

Python UNO(libreoffice):如何为工作表启用自动过滤器

[英]Python UNO (libreoffice): How to enable auto filters for a sheet

I have a program, that creates a CSV file.我有一个程序,它创建一个 CSV 文件。

Now I'd like to use a Python UNO script, which shall do several things:现在我想使用一个 Python UNO 脚本,它应该做几件事:

1.) open the csv file in a spread sheet 1.) 在电子表格中打开 csv 文件

2.) enable auto filter for all columns 2.) 为所有列启用自动过滤器

3.) create a macro and add it to the document 3.)创建一个宏并将其添加到文档中

4.) save the file as ODS file 4.) 将文件另存为 ODS 文件

This question concerns only 2.)这个问题只涉及2。)

1.) is working 1.) 正在工作

for 3.) I will probably create another question 1.) Is working (with pyoo and with unotools)对于 3.) 我可能会创建另一个问题 1.) 正在工作(使用 pyoo 和 unotools)

My steps so far:到目前为止我的步骤:

I start manually:我手动启动:

libreoffice --accept='socket,host=localhost,port=2202;urp;' --norestore --nologo --nodefault

My python script:我的python脚本:

With pyoo与表

import pyoo
# Step 0) connect to UNO bridge
desktop = pyoo.Desktop('localhost', 2002)

# Step 1) open the doc and get the sheet
# This works only if the field separator is a comma.
# I don't know how for example to specify tab as separator instead
doc = desktop.open_spreadsheet('tst.csv')
# I see the spreadsheet opening
sheet = doc.sheets[0] # I get an object of type Sheet

# Step2) set autofilter for active sheet
# no idea how to do

# Step3) create a macro and add it to the document
# no idea how to do but will create another question as 
# soon as step2 is solved

# Step 4) save the sheet
doc.save("tst_pyoo.ods")

Or with unotools或者使用 unotools

import unotools
from unotools.component.calc import Calc
from unotools.unohelper import convert_path_to_url

# Step 0) connect to UNO bridge
context = unotools.connect(unotools.Socket('localhost', 2002))

# Step 1) open document
doc = Calc(ctx, convert_path_to_url('tst.csv')
# I see the spreadsheet opening
sheet = doc.get_sheet_by_index(0)
# I get an object of type unotools.component.calc.Spreadsheet

# Step2) set autofilter for active sheet
# no idea how to do

# Step3) create a macro and add it to the document
# no idea how to do but will create another question as 
# soon as step2 is solved

# Step 4)
doc.store_to_url(convert_path_to_url("tst_unotools.ods"))

Thanks in advance for any feedback提前感谢您的任何反馈

Here is code that uses straight PyUNO rather than a wrapper library.这是使用直接 PyUNO 而不是包装库的代码。 It is adapted from http://www.imaccanici.org/en.libreofficeforum.org/node/5413.html .它改编自http://www.imaccanici.org/en.libreofficeforum.org/node/5413.html

import os
import uno

class UnoObjs:
    "Initializes and stores UNO objects to connect to a document."""
    def __init__(self, filepath=None):
        localContext = uno.getComponentContext()
        resolver = localContext.ServiceManager.createInstanceWithContext(
            "com.sun.star.bridge.UnoUrlResolver", localContext )
        self.ctx = resolver.resolve(
            "uno:socket,host=localhost,port=2002;urp;"
            "StarOffice.ComponentContext")
        self.smgr = self.ctx.ServiceManager
        desktop = self.smgr.createInstanceWithContext(
            "com.sun.star.frame.Desktop", self.ctx)
        if filepath:
            fileUrl = uno.systemPathToFileUrl(os.path.realpath(filepath))
            self.document = desktop.loadComponentFromURL(
                fileUrl, "_default", 0, ())
        else:
            self.document = desktop.getCurrentComponent()

def add_autofilter(unoObjs):
    """This adds an autofilter by selecting only the filled spreadsheet area. 
    NOTE: If any cell in the header row of the selection is empty this will
    trigger a popup for interactive user action (must click Yes for the
    Autofilter column header message box)
    """
    dispatcher = unoObjs.smgr.createInstanceWithContext(
        "com.sun.star.frame.DispatchHelper", unoObjs.ctx)
    controller = unoObjs.document.getCurrentController()
    sheet = unoObjs.document.getSheets().getByIndex(0)
    # select a sufficiently big "guess" area, hopefully
    guessRange = sheet.getCellRangeByPosition(0, 0, 150, 10000)
    # look up the actual used area within the guess area
    cursor = sheet.createCursorByRange(guessRange)
    cursor.gotoEndOfUsedArea(False)
    lastcol = cursor.RangeAddress.EndColumn
    lastrow = cursor.RangeAddress.EndRow
    # select the filled part of the spreadsheet
    actualRange = sheet.getCellRangeByPosition(0, 0, lastcol, lastrow)
    controller.select(actualRange)
    # add autofilter
    dispatcher.executeDispatch(
        unoObjs.document.getCurrentController(), ".uno:DataFilterAutoFilter",
        "", 0, ())

add_autofilter(UnoObjs("tst.csv"))

Dispatcher calls such as .uno:DataFilterAutoFilter are difficult to figure out the parameters.诸如.uno:DataFilterAutoFilter类的调度程序调用很难找出参数。 In most cases it's better to use UNO API calls such as XTextCursor instead.在大多数情况下,最好改用 UNO API 调用,例如XTextCursor However there are a few options to figure out dispatcher calls:但是,有几个选项可以确定调度员调用:

  • Use the macro recorder.使用宏记录器。
  • Look through a list like this one .通过看像一个列表这一个
  • Find the calls in the LibreOffice source code.在 LibreOffice 源代码中查找调用。 This is the most reliable, but it can still sometimes be difficult to determine the arguments.这是最可靠的,但有时仍然难以确定论点。

Regarding dispatcher calls, see https://forum.openoffice.org/en/forum/viewtopic.php?f=20&t=61127 .关于调度员调用,请参阅https://forum.openoffice.org/en/forum/viewtopic.php?f=20&t=61127

Is it possible to modify the content.xml directly contained in the .ods file with python?是否可以用python修改.ods文件中直接包含的content.xml

My aim is also to apply an autofilter in LibreOffice on Windows 10. I can't find any documentation whatsoever.我的目标也是在 Windows 10 上的 LibreOffice 中应用自动过滤器。我找不到任何文档。

But I found that if you unzip an .ods file, in the content.xml file there are the following lines of xml但是我发现如果你解压一个 .ods 文件,在 content.xml 文件中有以下几行 xml

<table:database-ranges>
                <table:database-range table:name="__Anonymous_Sheet_DB__0" table:target-range-address="Sheet1.A1:Sheet1.B3" table:display-filter-buttons="true"/>
</table:database-ranges>

Is there a way to read and modify the content.xml using the lxml module of python and in that way apply the autofilter in LibreOffice?有没有办法使用 python 的 lxml 模块读取和修改 content.xml 并以这种方式在 LibreOffice 中应用自动过滤器?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM