Openpyxl 问题:删除行不移动合并的单元格
Openpyxl Issue: Deleting row not moving merged cells
我在使用 openpxyl 删除一行而不向上移动合并的单元格时遇到问题。例如,在第一张图片中,我有两个具有值 Alex 和 Bob 的合并单元格。当我删除第 2 行时,Alex 向上移动到一个单元格,Bob 被删除,合并单元格的位置保持在同一位置,而其余数据点向上移动。当正常使用 Python 之外的 excel 时,合并的单元格只会与其余数据一起向上移动。看起来 openpxyl 想要向上移动数据值但保持合并单元格的位置不变。解决这个问题的方法是什么?提前致谢!!
删除第 2 行之前:
ws.delete_rows(2)
当我删除第 2 行时,会发生以下情况:
如果您在 excel 中手动删除第二行,它应该是什么样子:
我找到了一个临时但不令人满意的修复方法。
如果我使用下面的代码:
for merged_cell in ws.merged_cell.ranges:
merged_cell.shift(0,-1)
ws.delete_rows(2)
这将解决我的问题并将合并的单元格上移。但是,我对这段代码的一个问题是它向上移动了文件中所有合并的单元格。如果我只想将合并的单元格移到 A 列中,我不确定如何减少范围列表以仅包含 a.
例如,以下代码不起作用,但突出显示了我要具体实现的目标:
ws['A'].merged_cells.ranges
我在删除列时遇到了类似的问题,与此类列相交的合并单元格最终没有改变。
这样效果更令人满意。
代码提供了delete_row()
函数,可用于模仿Excel行为,并相应移动合并单元格:
import openpyxl
from openpyxl.utils import range_boundaries
from openpyxl.utils.cell import _get_column_letter
from openpyxl.worksheet.cell_range import CellRange
def delete_row(target_row):
# Assuming that the workbook from the example is the first worksheet in a file called "in.xlsx"
workbook = openpyxl.load_workbook('in.xlsx')
ws = workbook.worksheets[0]
affected_cells = [] # array for storing merged cells that need to be moved
row = target_row # specify the row that we want to delete
sheet_boundary = [4,6] # specify how far to search for merged cells in the sheet in the format of [ max_col, max_row ]
## Define a range of cells that are below the deleted row
# top left corner of the range; will be A2
tl_corner = "A"+str(row)
# bottom right corner of the row; will be D6
br_corner = _get_column_letter(sheet_boundary[0]) + str(sheet_boundary[1])
target_row_range_string = tl_corner+":"+br_corner
# express all cells in the row that is to be deleted as object CellRange from openpyxl
target_range = CellRange(range_string=target_row_range_string)
# loop over all merged cells in the sheet
for merged_cell_range in ws.merged_cells.ranges:
# if merged_cell is within target_range add current merged cell to 'affected_cells'
if merged_cell_range.issubset(target_range):
print("Cell '"+str(merged_cell_range)+"' is within range of '"+str(target_range)+"'")
affected_cells.append(merged_cell_range)
# unmerge all affected cells
for cell in affected_cells:
# get a tuple of coordinates, instead of Xlsx notation
cell_range = range_boundaries(cell.coord)
print("'"+str(cell)+"' ---> '"+str(cell_range)+"'")
# unmerge the affected cell
ws.unmerge_cells(start_column = cell_range[0], start_row = cell_range[1],
end_column = cell_range[2], end_row = cell_range[3])
# perform row deletion as usual
ws.delete_rows(row)
# merged all affected cells
for cell in affected_cells:
# get a tuple of coordinates, instead of Xlsx notation
cell_range = range_boundaries(cell.coord)
# merge back the affected cell, while lifting it up by one row
ws.merge_cells(start_column = cell_range[0], start_row = cell_range[1]-1,
end_column = cell_range[2], end_row = cell_range[3]-1)
# save the edited workbook
workbook.save('out.xlsx')
# call our custom function, specifying the row you want to delete
delete_row(2)
这会找到与 target_range
相交的所有合并单元格,范围从删除的行开始,到 sheet_boundary
定义的范围结束,并首先取消合并它们。
仅更改完全在 target_range
内的合并单元格。
如果合并单元格的一部分在 target_range
内,则不会对该单元格执行任何操作。
然后删除所需的行,并合并回所有受影响的单元格,同时考虑到它们已向上移动了一行。
我在使用 openpxyl 删除一行而不向上移动合并的单元格时遇到问题。例如,在第一张图片中,我有两个具有值 Alex 和 Bob 的合并单元格。当我删除第 2 行时,Alex 向上移动到一个单元格,Bob 被删除,合并单元格的位置保持在同一位置,而其余数据点向上移动。当正常使用 Python 之外的 excel 时,合并的单元格只会与其余数据一起向上移动。看起来 openpxyl 想要向上移动数据值但保持合并单元格的位置不变。解决这个问题的方法是什么?提前致谢!!
删除第 2 行之前:
ws.delete_rows(2)
当我删除第 2 行时,会发生以下情况:
如果您在 excel 中手动删除第二行,它应该是什么样子:
我找到了一个临时但不令人满意的修复方法。
如果我使用下面的代码:
for merged_cell in ws.merged_cell.ranges:
merged_cell.shift(0,-1)
ws.delete_rows(2)
这将解决我的问题并将合并的单元格上移。但是,我对这段代码的一个问题是它向上移动了文件中所有合并的单元格。如果我只想将合并的单元格移到 A 列中,我不确定如何减少范围列表以仅包含 a.
例如,以下代码不起作用,但突出显示了我要具体实现的目标:
ws['A'].merged_cells.ranges
我在删除列时遇到了类似的问题,与此类列相交的合并单元格最终没有改变。
这样效果更令人满意。
代码提供了delete_row()
函数,可用于模仿Excel行为,并相应移动合并单元格:
import openpyxl
from openpyxl.utils import range_boundaries
from openpyxl.utils.cell import _get_column_letter
from openpyxl.worksheet.cell_range import CellRange
def delete_row(target_row):
# Assuming that the workbook from the example is the first worksheet in a file called "in.xlsx"
workbook = openpyxl.load_workbook('in.xlsx')
ws = workbook.worksheets[0]
affected_cells = [] # array for storing merged cells that need to be moved
row = target_row # specify the row that we want to delete
sheet_boundary = [4,6] # specify how far to search for merged cells in the sheet in the format of [ max_col, max_row ]
## Define a range of cells that are below the deleted row
# top left corner of the range; will be A2
tl_corner = "A"+str(row)
# bottom right corner of the row; will be D6
br_corner = _get_column_letter(sheet_boundary[0]) + str(sheet_boundary[1])
target_row_range_string = tl_corner+":"+br_corner
# express all cells in the row that is to be deleted as object CellRange from openpyxl
target_range = CellRange(range_string=target_row_range_string)
# loop over all merged cells in the sheet
for merged_cell_range in ws.merged_cells.ranges:
# if merged_cell is within target_range add current merged cell to 'affected_cells'
if merged_cell_range.issubset(target_range):
print("Cell '"+str(merged_cell_range)+"' is within range of '"+str(target_range)+"'")
affected_cells.append(merged_cell_range)
# unmerge all affected cells
for cell in affected_cells:
# get a tuple of coordinates, instead of Xlsx notation
cell_range = range_boundaries(cell.coord)
print("'"+str(cell)+"' ---> '"+str(cell_range)+"'")
# unmerge the affected cell
ws.unmerge_cells(start_column = cell_range[0], start_row = cell_range[1],
end_column = cell_range[2], end_row = cell_range[3])
# perform row deletion as usual
ws.delete_rows(row)
# merged all affected cells
for cell in affected_cells:
# get a tuple of coordinates, instead of Xlsx notation
cell_range = range_boundaries(cell.coord)
# merge back the affected cell, while lifting it up by one row
ws.merge_cells(start_column = cell_range[0], start_row = cell_range[1]-1,
end_column = cell_range[2], end_row = cell_range[3]-1)
# save the edited workbook
workbook.save('out.xlsx')
# call our custom function, specifying the row you want to delete
delete_row(2)
这会找到与 target_range
相交的所有合并单元格,范围从删除的行开始,到 sheet_boundary
定义的范围结束,并首先取消合并它们。
仅更改完全在 target_range
内的合并单元格。
如果合并单元格的一部分在 target_range
内,则不会对该单元格执行任何操作。
然后删除所需的行,并合并回所有受影响的单元格,同时考虑到它们已向上移动了一行。