Jos*_*Fox 2 python excel openpyxl
Openpyxl 可以告诉我Excel 工作表的“使用范围”max_row和max_col“使用范围”。但是,此范围可以包括没有内容的单元格,前提是它们以前被选中或更改过。
我想知道具有内容的最后一列和最后一行。
例如,如果- 此处表示已用范围中的_空白并表示已使用范围之外的空白,我想选择标有 的列b和标有的行c,即使 Openpyxl 和 将在计算max_row和max_col时包括带破折号的行/列。
aaaaa---__
aaaaa-b-__
aaaaa---__
--------__
--c-----__
--------__
__________
__________
Run Code Online (Sandbox Code Playgroud)
我发现 openpyxl 确实为已保存的文件报告了 max_row 和 max_col 的正确值,但是如果您操作工作表的内容并在保存前需要这些值,问题仍然存在。
没有内置的方法来执行此操作,因此您最好的选择是自己搜索行和列,最好通过从报告的值开始并向上和向左搜索来限制搜索。
工作表对象允许您单独访问行,但只能通过.itercols(). 这是否比在一个循环中扫描所有列更快取决于您期望工作表的空程度。
from openpyxl import load_workbook
wb = load_workbook('test.xlsx')
wb.worksheets[0]['h6'] = None
print((wb.worksheets[0].max_row, wb.worksheets[0].max_column))
def find_edges(sheet):
row = sheet.max_row
while row > 0:
cells = sheet[row]
if all([cell.value is None for cell in cells]):
row -= 1
else:
break
if row == 0:
return 0, 0
column = sheet.max_column
while column > 0:
cells = next(sheet.iter_cols(min_col=column, max_col=column, max_row=row))
if all([cell.value is None for cell in cells]):
column -= 1
else:
break
return row, column
print(find_edges(wb.worksheets[0]))
Run Code Online (Sandbox Code Playgroud)
在此示例中,我加载了一个 Excel 工作表,其中包含您所建议的数据,并且值仍在 中H6,该值已在第 3 行中删除。
它首先打印max_row和max_column报告的openpyxl和 然后调用工作find_edges表,以找到所需的实际值。
对于数据很少的大型工作表,您可能希望通过简单地迭代所有列来尝试替换列扫描以提高速度,一旦您确定了最后一行(以限制大小),如下所示:
columns = sheet.iter_cols(max_row=row)
column = 1
ci = 1
while True:
try:
cells = next(columns)
if not all([cell.value is None for cell in cells]):
column = ci
ci += 1
except StopIteration:
break
Run Code Online (Sandbox Code Playgroud)
但我希望第一种方法对于大多数有用的用例来说是最快的。
如果你更喜欢简短而不是可读:
def find_edges2(sheet):
def row():
for r in range(sheet.max_row, 0, -1):
if not all([cell.value is None for cell in sheet[r]]):
return r
row = row()
if not row:
return 0, 0
def column():
for c in range(sheet.max_column, 0, -1):
if not all([cell.value is None for cell in next(sheet.iter_cols(min_col=c, max_col=c, max_row=row))]):
return c
return row, column()
Run Code Online (Sandbox Code Playgroud)