Python 3.x Openpyxl问题:删除行而不移动合并单元格

Python 3.x Openpyxl问题:删除行而不移动合并单元格,python-3.x,openpyxl,Python 3.x,Openpyxl,我对openpxyl删除一行而不向上移动合并的单元格有问题。例如,在第一张图片中,我有两个值为Alex和Bob的合并单元格。当我删除第2行时,Alex上移到单个单元格,Bob被删除,合并单元格的位置保持在同一位置,而其余数据点上移。通常在Python之外使用excel时,合并的单元格只会随着其余数据向上移动。openpxyl似乎希望向上移动数据值,但保持合并单元格的位置不变。这方面的工作是什么?提前谢谢你 删除第2行之前: 删除第2行时,会发生以下情况: 如果您在excel中手动删除第二行,

我对openpxyl删除一行而不向上移动合并的单元格有问题。例如,在第一张图片中,我有两个值为Alex和Bob的合并单元格。当我删除第2行时,Alex上移到单个单元格,Bob被删除,合并单元格的位置保持在同一位置,而其余数据点上移。通常在Python之外使用excel时,合并的单元格只会随着其余数据向上移动。openpxyl似乎希望向上移动数据值,但保持合并单元格的位置不变。这方面的工作是什么?提前谢谢你

删除第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)
这将查找与
目标\u范围
相交的所有合并单元格,该范围以删除的行开始,以
图纸\u边界
定义的范围结束,然后首先取消合并

仅更改完全在目标范围内的合并单元格。 如果合并单元格的一部分在
目标范围内
,则不会对该单元格执行任何操作


然后删除所需的行,并合并回所有受影响的单元格,同时考虑到它们已上移一行。

您必须自己执行此操作,与公式或引用的操作相同。
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)