原因
Apache POI写出来的excel文件,sheetX.xml 中 dimension tag的ref为 A1(正常的excel文件为A1:XXX,XXX指最后一个单元格)
处理
重载openpyxl 的WorkSheetParser类中 WorkSheetParser.parse_dimensions 方法
from openpyxl.worksheet._reader import WorkSheetParser, ROW_TAG, DATA_TAG, CELL_TAG, DIMENSION_TAG
from openpyxl.worksheet.dimensions import SheetDimension
from openpyxl import load_workbook
from openpyxl.utils.cell import range_boundaries
from lxml import etree
def new_parse_dimisions(self):
# 预设置一个 boundaries
boundaries = (1, 1, 1, 1)
try:
# 解析成etree(使用lxml模块)
tree = etree.parse(self.source)
# 尝试查找dimenssion
dimension_elem = tree.find(f'//{DIMENSION_TAG}')
dim = SheetDimension.from_tree(dimension_elem) if dimension_elem else None
# 如果没有Dimension信息, 或 Dimension只有A1
if not dim or dim.boundaries == (1,1,1,1):
# 查找最后一个单元格, [last()]会影响效率
last_cell = tree.findall(f'//{DATA_TAG}/{ROW_TAG}/{CELL_TAG}')[-1]
# cell标签的r属性中,就是最后一个单元格的地址,解析失败的情况下,就用A1兜底。
last_cell_address = last_cell.get('r', 'A1')
# 将单元格区域转为tuple
boundaries = range_boundaries(f'A1:{last_cell_address}')
return boundaries
else:
boundaries = dim.boundaries if dim else (1, 1, 1, 1)
finally:
return boundaries
# 重载方法
WorkSheetParser.parse_dimensions = new_parse_dimisions