大家好,我们经常会有这样的需求。比如下图
我们需要把同一个省份的合并起来,如下图的效果
如何实现呢,这是原有的df
直观的操作是这样的:
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里面,请看!
#-*- 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("",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("<>",lambda event:getmergeseg(event,alldata,sheetvar.get()))
#勾选目标字段
def getmergeseg(event,alldata,sheet):
global frame2,segvars
segvars&#61;[]
try:
frame2.destroy()
except:
pass
frame2&#61;tk.Frame(window,padx&#61;15,pady&#61;6)
frame2.grid(row&#61;1,column&#61;0,sticky&#61;&#39;w&#39;)
ttk.Label(frame2,text&#61;"请勾选分组合并的目标字段(第一个勾选框为分组合并依据&#xff0c;必须事先进行排序:").grid(row&#61;0,column&#61;0,columnspan&#61;4,sticky&#61;&#39;w&#39;)
data&#61;alldata[sheet]
for index,item in enumerate(data.columns):
segvars.append(tk.StringVar())
ttk.Checkbutton(frame2,text&#61;item,variable&#61;segvars[-1],onvalue&#61;item,offvalue&#61;&#39;&#39;).grid(row&#61;(index//4&#43;1),column&#61;index%4,sticky&#61;&#39;w&#39;)
#合并字段单元格
def merging(file,sheet,segvars):
selected&#61;[i.get() for i in segvars if i.get()]
df&#61;pd.read_excel(file,sheet)
wb&#61;load_workbook(file)
ws&#61;wb[sheet]
mergecells(ws,df,selected)
try:
wb.save(file)
messagebox.showinfo(&#39;提示&#39;,file&#43;&#39;-&#39;&#43;sheet&#43;&#39;指定单元格合并完成&#39;)
os.system(&#39;start &#39;&#43;os.path.dirname(file))
except Exception as e:
messagebox.showerror(&#39;警告&#39;,str(e))
#合并单元格函数
def mergecells(ws,df,cols):
col&#61;cols[0]
gdic&#61;df.groupby(col).groups
aligncenter&#61;Alignment(horizontal&#61;&#39;center&#39;,vertical&#61;&#39;center&#39;)
for gname in gdic:
indexs&#61;gdic[gname]&#43;2
indexs&#61;indexs.sort_values()
for col in cols: #每一个要合并的字段
colindex&#61;df.columns.tolist().index(col)&#43;1
ws.merge_cells(start_row&#61;indexs[0],end_row&#61;indexs[-1],start_column&#61;colindex,end_column&#61;colindex) #合并
for i in range(1,ws.max_row&#43;1): #实现居中
ws.cell(row&#61;i,column&#61;colindex).alignment&#61;aligncenter
def manual(): #使用说明
info&#61;"""
作用是合并单元格&#xff0c;把同样内容的单元格合并到一起&#xff0c;所以必须实现对目标字段进行排序&#xff0c;否则无法实现合并
"""
messagebox.showinfo(&#39;提示&#39;,info)
frame1&#61;tk.Frame(window,pady&#61;6,padx&#61;15)
frame1.grid(row&#61;0,column&#61;0,sticky&#61;&#39;w&#39;)
ttk.Button(frame1,text&#61;"打开目标文件",command&#61;getmergefile).grid(row&#61;0,column&#61;0,sticky&#61;&#39;w&#39;)
ttk.Entry(frame1,textvariable&#61;path_tar,width&#61;40).grid(row&#61;0,column&#61;1)
frame3&#61;tk.Frame(window,pady&#61;10,padx&#61;15)
frame3.grid(row&#61;2,column&#61;0,sticky&#61;&#39;w&#39;)
ttk.Button(frame3,text&#61;"点击合并单元格",command&#61;lambda:merging(path_tar.get(),sheetvar.get(),segvars)).grid(row&#61;0,column&#61;0,sticky&#61;&#39;w&#39;)
ttk.Button(frame3,text&#61;"使用说明",command&#61;manual).grid(row&#61;0,column&#61;1)
window.mainloop()
效果如图&#xff1a;
以上就是本文的全部内容&#xff0c;希望对大家的学习有所帮助&#xff0c;也希望大家多多支持站圈网。