大家好,我们经常会有这样的需求。比如下图
我们需要把同一个省份的合并起来,如下图的效果
如何实现呢,这是原有的df
直观的操作是这样的:
1
2
3
4
5
6
7
8
9
10
11
|
df.to_excel( 'test.xlsx' ,index = false)
from openpyxl import load_workbook
wb = load_workbook( 'test.xlsx' )
ws = wb.active()
ws.merge_cells(start_row = 2 ,end_row = 8 ,start_column = 1 ,end_column = 1 )
ws.merge_cells(start_row = 2 ,end_row = 8 ,start_column = 2 ,end_column = 2 )
ws.merge_cells(start_row = 9 ,end_row = 14 ,start_column = 1 ,end_column = 1 )
ws.merge_cells(start_row = 9 ,end_row = 14 ,start_column = 2 ,end_column = 2 )
ws.merge_cells(start_row = 15 ,end_row = 18 ,start_column = 1 ,end_column = 1 )
ws.merge_cells(start_row = 15 ,end_row = 18 ,start_column = 2 ,end_column = 2 )
wb.save()
|
只是问题在于我们不能总是人工判断start_row和end_row,如何能使程序自动获取row的起始点呢?其实我们使用一个groupby就发现了方法了!大家看到了吗?
真是柳暗花明又一村啊,完整解决方案已经有了,我封装到了tkinter里面,请看!
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
|
#-*- coding:utf-8 -*-
import tkinter as tk #使用tkinter前需要先导入
from tkinter import filedialog,messagebox,ttk
from openpyxl import load_workbook
from openpyxl.styles import alignment
import os
import pandas as pd
#建立窗口window
window = tk.tk()
window.title( 'excel合并单元格工具' )
w_width = 630
w_height = 600
scn_width = window.maxsize()[ 0 ]
x_point = (scn_width - w_width) / / 2
window.geometry( '%dx%d+%d+%d' % (w_width,w_height,x_point, 100 ))
window.wm_attributes( '-topmost' ,true)
window.tk_focusfollowsmouse()
window.bind( "<escape>" , lambda event:window.iconify())
path_tar = tk.stringvar()
sheetvar = tk.stringvar() #目标工作表
#打开目标文件
def getmergefile():
file_path = filedialog.askopenfilename(title = u '选择文件' ,filetype = [( 'excel' , '.xlsx' )])
path_tar. set (file_path)
alldata = pd.read_excel(file_path,none)
ttk.label(frame1,text = "请选择目标工作表:" ).grid(row = 1 ,column = 0 ,sticky = 'w' )
global sheetvar
chosen_sheet = ttk.combobox(frame1,width = 16 ,textvariable = sheetvar)
chosen_sheet[ 'values' ] = list (alldata)
chosen_sheet.grid(row = 1 ,column = 1 ,sticky = 'w' )
chosen_sheet.bind( "<<comboboxselected>>" , lambda event:getmergeseg(event,alldata,sheetvar.get()))
#勾选目标字段
def getmergeseg(event,alldata,sheet):
global frame2,segvars
segvars = []
try :
frame2.destroy()
except :
pass
frame2 = tk.frame(window,padx = 15 ,pady = 6 )
frame2.grid(row = 1 ,column = 0 ,sticky = 'w' )
ttk.label(frame2,text = "请勾选分组合并的目标字段(第一个勾选框为分组合并依据,必须事先进行排序:" ).grid(row = 0 ,column = 0 ,columnspan = 4 ,sticky = 'w' )
data = alldata[sheet]
for index,item in enumerate (data.columns):
segvars.append(tk.stringvar())
ttk.checkbutton(frame2,text = item,variable = segvars[ - 1 ],onvalue = item,offvalue = ' ').grid(row=(index//4+1),column=index%4,sticky=' w')
#合并字段单元格
def merging( file ,sheet,segvars):
selected = [i.get() for i in segvars if i.get()]
df = pd.read_excel( file ,sheet)
wb = load_workbook( file )
ws = wb[sheet]
mergecells(ws,df,selected)
try :
wb.save( file )
messagebox.showinfo( '提示' , file + '-' + sheet + '指定单元格合并完成' )
os.system( 'start ' + os.path.dirname( file ))
except exception as e:
messagebox.showerror( '警告' , str (e))
#合并单元格函数
def mergecells(ws,df,cols):
col = cols[ 0 ]
gdic = df.groupby(col).groups
aligncenter = alignment(horizontal = 'center' ,vertical = 'center' )
for gname in gdic:
indexs = gdic[gname] + 2
indexs = indexs.sort_values()
for col in cols: #每一个要合并的字段
colindex = df.columns.tolist().index(col) + 1
ws.merge_cells(start_row = indexs[ 0 ],end_row = indexs[ - 1 ],start_column = colindex,end_column = colindex) #合并
for i in range ( 1 ,ws.max_row + 1 ): #实现居中
ws.cell(row = i,column = colindex).alignment = aligncenter
def manual(): #使用说明
info = """
作用是合并单元格,把同样内容的单元格合并到一起,所以必须实现对目标字段进行排序,否则无法实现合并
"""
messagebox.showinfo( '提示' ,info)
frame1 = tk.frame(window,pady = 6 ,padx = 15 )
frame1.grid(row = 0 ,column = 0 ,sticky = 'w' )
ttk.button(frame1,text = "打开目标文件" ,command = getmergefile).grid(row = 0 ,column = 0 ,sticky = 'w' )
ttk.entry(frame1,textvariable = path_tar,width = 40 ).grid(row = 0 ,column = 1 )
frame3 = tk.frame(window,pady = 10 ,padx = 15 )
frame3.grid(row = 2 ,column = 0 ,sticky = 'w' )
ttk.button(frame3,text = "点击合并单元格" ,command = lambda :merging(path_tar.get(),sheetvar.get(),segvars)).grid(row = 0 ,column = 0 ,sticky = 'w' )
ttk.button(frame3,text = "使用说明" ,command = manual).grid(row = 0 ,column = 1 )
window.mainloop()
|
效果如图:
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持服务器之家。
原文链接:https://blog.csdn.net/chaodaibing/article/details/108320039