Я обнаружил, что 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]))
В этом примере я загружаю лист Excel, содержащий именно те данные, которые вы предложили, сзначение также все еще находится в H6
, которое удаляется в строке 3.
Сначала оно печатает max_row
и max_column
, как сообщается openpyxl
, а затем вызывает find_edges
с листом, чтобынайдите фактические требуемые значения.
Для больших листов с очень небольшим объемом данных вы можете поэкспериментировать для ускорения с заменой сканирования столбцов, просто повторяя все столбцы, как только вы определили последнюю строку (для ограниченияsize), например, так:
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
Но я ожидаю, что первый способ наиболее быстрый для наиболее полезных случаев использования.
Если вы предпочитаете короткий, а не читаемый:
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()