Openpyxl。忽略具有样式但没有值的单元格

时间:2020-09-30 19:09:47

标签: python excel openpyxl

我想知道是否有一种方法可以使openpyxl忽略没有值的单元格?单元格位于xml树中,但没有值,只有样式已定义

问题是,我有一张工作表,其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的情况也是如此,由于在ws.iter_rows方法中解析XML树中的行的方式,我得到了一百万个空行。我看到它背后的逻辑,并且我知道这是xlsx文件本身的问题,但是我想知道是否可以使用openpyxl API处理它?<​​/ p>

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

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

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-感觉没人遇到过这样的问题:(

1 个答案:

答案 0 :(得分:1)

您最好对parse_row()进行修补,这是对这些东西进行控制的地方。这比弄乱解析器更容易使用和最简单。