我想知道是否有一种方法可以使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_row
和ws.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-感觉没人遇到过这样的问题:(
答案 0 :(得分:1)
您最好对parse_row()
进行修补,这是对这些东西进行控制的地方。这比弄乱解析器更容易使用和最简单。