打开pyxl。忽略具有样式但没有值的单元格

Openpyxl. Ignoring cells that have style but have no values

我想知道有没有办法让 openpyxl 忽略没有值的单元格?单元格位于 xml 树中,但没有值,仅定义了样式

问题是,我有一个sheet,它的xml结构是这样的:

<row r="18" spans="3:9 16384:16384" ht="15" customHeight="1" thickBot="1">
    <c r="C18" s="14" t="s">
        <v>24</v>
    </c>
    <c r="D18" s="14" t="s">
        <v>25</v>
    </c>
    <c r="E18" s="14" t="s">
        <v>27</v>
    </c>
    ...
    <c r="I18" s="12"/>
    <c r="XFD18" s="13"/>
</row>
<row r="1048576" spans="4:4" ht="15" customHeight="1">
    <c r="D1048576" s="13"/>
</row>

openpyxl到达第18行并尝试获取单元格时,它生成单元格的方式使其用16336个空单元格填充单元格I18和XFD18之间的空隙。对于第 18 - 1048576 行也是如此,由于 XML 树中的行在 ws.iter_rows 方法中被解析的方式,我得到了一百万个空行。我看到了背后的逻辑,我知道这是 xlsx 文件本身的问题,但我想知道这是否是我可以使用 openpyxl API?

处理的问题

我知道 xlrd 会忽略空单元格格式(只是没有实现),因此 xlrd 不会将此类单元格添加到行中。有没有办法让 openpyxl 行为相同?查看源代码,除了为 ws.iter_rows 方法定义 max_columnmax_row 之外,我看不到使用现有 API 的方法(这不是最佳的,因为实际数量columns/rows 可能会有所不同)

我设法完成了修改 xml_source 的任务(wb 打开为 read_only):

import io
import xml.etree.ElementTree as ET

from openpyxl.xml.functions import iterparse, safe_iterator
from openpyxl.xml.constants import SHEET_MAIN_NS


ROW_TAG = '{%s}row' % SHEET_MAIN_NS
CELL_TAG = '{%s}c' % SHEET_MAIN_NS
VALUE_TAG = '{%s}v' % SHEET_MAIN_NS
SHEET_DATA = '{%s}sheetData' % SHEET_MAIN_NS

def clean_up_xml_from_empty_rows_and_cells(sheet):
    sheet_data = None

    rows_to_delete = set()
    p = iterparse(sheet.xml_source, tag=[ROW_TAG], remove_blank_text=True)
    for _event, element in p:

        if element.tag == SHEET_DATA:
            sheet_data = element
            continue

        if element.tag == ROW_TAG:
            cells_to_delete = set()
            for cell in safe_iterator(element, CELL_TAG):
                if cell.findtext(VALUE_TAG) is None:
                    cells_to_delete.add(cell)

            for cell in cells_to_delete:
                element.remove(cell)

            if not len(element):
                rows_to_delete.add(element)

    for row in rows_to_delete:
        sheet_data.remove(row)

    out_file = io.BytesIO()

    element_tree = ET.ElementTree(p.root)
    element_tree.write(out_file, encoding='utf8')
    out_file.seek(0)

    sheet.xml_source = out_file

可是感觉好不对啊!如此危险,我绝对不确定这样的功能不会破坏其他 xlsx 文件的解析。

真的没有办法忽略没有值的单元格吗?浏览SO和google——感觉从来没有人遇到过这样的问题:(

你可能最好不要修补 parse_row(),这是控制这些东西的地方。这比搞乱解析器更容易使用。