- 任务
需求描述是:将C列的内容(3,4,5)合并在一起之后,将5,6,7三行合并成一行
效果如下:
2.思路
需求很清晰,简单。但是数据量不是上面这样简单的几行
在原数据中,我们要合并的内容就是E列(对应上述的C列)。
在A列(通话开始时间)中,有些时间单元格是合并单元格,有些不是,只有对于合并单元格的,它对应的E列才需要我们合并。
所以,先找出A列合并的单元格,对于其同行的E列内容进行合并,最后将相应的行合并为一行
- 编码
① 找出合并的单元格。excel的合并单元格中,只有单元格的第一行内容是不为空的,其余行内容为空。所以直观思路是遍历A列的单元格,如果行内容为空,就开始记录行数,直到遇到下一个不为空的内容。之间记录的行数就是合并单元格的行数范围。
但是这样有些“呆”。openpyxl给我们提供了现成的方法:
sheet.merged_cells
该方法会返回一个列表,包含了所有合并单元格的范围。我们print输出sheet.merged_cells,结果如下:
以第一项为例,“A4:A9”,表明A列第四行到第九行是合并单元格。至此第一个目标实现
②将E列的内容合并。
首先我们需要获取合并单元格的行范围,方便后续 *** 作。很简单的一个字符串处理,不赘述。
for crange in sheet.merged_cells: cells=str(crange) if cells[0]!='A': break index=cells.find(':') start=cells[1:index] end=cells[index+2:]
合并单元格,openpyxl给我们提供的方法是sheet.merge_cells('start:end')
但是该方法 *** 作,不等同于合并单元格内容。也就是说,会将若干行单元格合并,同时内容只保留第一行的。
所以我们需要遍历start to end,先将每一行内容保存到一起,然后合并单元格后,将内容存回去。
content="" area=sheet[f'E{start}:E{end}'] for i in area: for j in i: if(j.value!=None): content+=(j.value+'n') sheet.merge_cells(f'E{start}:E{end}') sheet['E'+f'{start}'].value=content
③将多行合并成一行。
以最开始那张图为例,6/7行是冗余的,我们希望将5,6,7行合并成一行。
最直接的想法是删掉5,6,7行。我们也这样做了。
代码很简单,
sheet.delete_rows(idx=int(start)+1,amount=int(end)-int(start))
但是效果是错的。会发现,有很多单元格莫名其妙地被删掉了,似乎没有任何规律可循
分析之后,结论是:在初始的for循环当中:
for crange in sheet.merged_cells:
**这里的merged_cells的内容是一次生成的,不是每次取出一个crange的时候,就去run一遍sheet.merged_cells,更新一遍。**比如这个list的内容是[1 2 3],那么这个for循环就相当于一个指针在遍历list的内容。
问题就在这里,我们每次取出一个单元格,del掉多余的行之后,后面的行是会顺位补上去的。,也就导致,后面那些合并单元格,其位置会变化。
比如A4:A9是一个合并单元格。A10:A11是一个合并单元格。
将5-9行多余的删去后,10-11行顺位上填充,变成了A5-A6.但是我们的merged_cells并没有变化,所以删的时候还是删的11行,这就导致很多行被莫名其妙删掉。
另外一个问题是:由于我们AB,C,D等列的对应内容是合并单元格,所以如果想要del掉多余的列的话,只会del掉E列(5-9)行,(此时我们E列还没有合并的情况下。)
也就是对于A4:A9,直接del 5-9行,ABCD列的行内容不会被删,但是E列的会被删。于是就出现了E列内容错位的问题。
如何规避以上问题?
将E列内容合并后,将所有合并单元格拆解。
然后遍历每一行,如果单元格内容为空,则del掉。
list=[] for crange in sheet.merged_cells: cells=str(crange) list.append(cells) #print(list) for cell in list: sheet.unmerge_cells(cell) i=1 content=sheet['A'] for cell in content: #print(cell.value) if cell.value==None: sheet.delete_rows(i) else:i+=1
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)