当前位置:网站首页>Merge two excel spreadsheet tools
Merge two excel spreadsheet tools
2022-08-03 01:32:00 【Andy Dennis】
前言
We sometimes need to merge two related tables.例如表格1有“考生号, 姓名, 语文成绩”字段,表格2有“考生号, 姓名, 数学成绩”,So now you need to merge two form as “考生号, 姓名, 语文成绩, 数学成绩”.
示例
原来a, b表格
导出后:
代码
main.py
""" Author: Andy Dennis Date: 2022.7.29 Details: 其中ComBoPicker代码来自https://blog.csdn.net/weixin_45774074/article/details/123293411 """
from tkinter import *
import tkinter as tk
from ComBoPicker import Combopicker# Import custom drop-down boxes,
import tkinter.font as tf
from tkinter import filedialog, messagebox
import traceback
import pandas as pd
main_xlsx = ''
aux_xlsx = ''
join_df = None
# Select the main table
def select_main_xlsx():
global main_xlsx
global join_df
fp = filedialog.askopenfilename(title=u'Please select the main table')
print(fp)
try:
if fp is not None and len(fp) > 0:
if fp.split('.')[-1] not in ['xls', 'xlsx']:
tk.messagebox.showerror('error', '请选择xls/xlsx的文件')
return
main_xlsx = fp
lb1['text'] = fp
join_df = None
print('main_xlsx: ', main_xlsx)
lb5['text'] = 'No hint'
# tk.messagebox.showinfo('success', '选择原始目录成功')
else:
tk.messagebox.showerror('error', 'Please select the main failure')
except:
tk.messagebox.showerror('error', 'Please select the main failure')
print(traceback.format_exc())
# Select the side tables
def select_aux_xlsx():
global aux_xlsx
global join_df
fp = filedialog.askopenfilename(title=u'Please select the side tables')
print(fp)
try:
if fp is not None and len(fp) > 0:
if fp.split('.')[-1] not in ['xls', 'xlsx']:
tk.messagebox.showerror('error', '请选择xls/xlsx的文件')
return
aux_xlsx = fp
lb2['text'] = fp
join_df = None
print('aux_xlsx: ', aux_xlsx)
lb5['text'] = 'No hint'
# tk.messagebox.showinfo('success', '选择原始目录成功')
else:
tk.messagebox.showerror('error', 'Please select the side tables failed')
except:
tk.messagebox.showerror('error', 'Please select the side tables failed')
print(traceback.format_exc())
# Delete the drop-down box and create a new
def destroy_and_new_one(values):
global COMBOPICKER1
global window
COMBOPICKER1.destroy()
COMBOPICKER1 = Combopicker(window, values=values, entrywidth=50)
COMBOPICKER1.place(x=100, y=160)
def join_xlsx():
global COMBOPICKER1
global join_df
if main_xlsx == '' or aux_xlsx == '':
tk.messagebox.showerror('error', 'Please select the main table and side tables')
return
main_df = pd.read_excel(main_xlsx)
aux_df = pd.read_excel(aux_xlsx)
main_df_cols = main_df.columns
aux_df_cols = aux_df.columns
print('main_df_cols: ', main_df_cols)
print('aux_df_cols: ', aux_df_cols)
join_cols_set = set(main_df_cols) & set(aux_df_cols)
# 主键, I directly to the same field name here(列名)作为主键了
key_cols = [item for item in main_df_cols if item in join_cols_set]
print('key_cols: ', key_cols)
union_cols = [item for item in main_df_cols]
# Add schedule other columns
for item in aux_df_cols:
if item not in union_cols:
union_cols.append(item)
print('union_cols: ', union_cols)
join_df = pd.merge(main_df, aux_df, on=key_cols, how='left')
print('join_df:\n', join_df)
destroy_and_new_one(union_cols)
lb5['text'] = 'No hint'
def save_a_excel(save_df):
fp = filedialog.asksaveasfilename(defaultextension='合并后的文件',filetypes=[("excel文件", ".xlsx")])
print(fp)
try:
if fp is not None and len(fp) > 0:
if fp.split('.')[-1] not in ['xls', 'xlsx']:
tk.messagebox.showerror('error', '请保存为xls/xlsx格式的文件')
return
save_df.to_excel(fp, index=False,header=True)
# tk.messagebox.showinfo('success', '选择原始目录成功')
else:
tk.messagebox.showerror('error', 'Save merge table failed')
except:
tk.messagebox.showerror('error', 'Save merge table failed')
print(traceback.format_exc())
def save_xlsx():
global join_df
if main_xlsx == '' or aux_xlsx == '':
tk.messagebox.showerror('error', 'Please select the main table and side tables')
return
if join_df is None:
tk.messagebox.showerror('error', 'Please click on the combined form button')
return
choose_items = COMBOPICKER1.get()
print(choose_items)
if len(choose_items) == 0:
tk.messagebox.showerror('error', 'Please choose to export the column name')
return
else:
choose_items = choose_items.split(',')
union_cols = join_df.columns
save_cols = [item for item in union_cols if item in choose_items]
print('导出列: ', save_cols)
lb5['text'] = '导出列: ' + ' '.join(save_cols)
save_df = join_df[save_cols]
print(save_df)
save_a_excel(save_df)
if __name__ == "__main__":
window = Tk()
# 标题
window.title('合并XLSX小软件')
window.geometry("500x300")
# 不允许重新设置大小
window.resizable('true', 'true')
bt1 = tk.Button(window, text='Select the main table', width=12, height=1, font=tf.Font(size=12), command=select_main_xlsx)
bt1.place(x=60, y=24)
bt2 = tk.Button(window, text='Select the side tables', width=12, height=1, font=tf.Font(size=12), command=select_aux_xlsx)
bt2.place(x=220, y=24)
lb1 = tk.Label(window, text='Did not select the main table', font=tf.Font(size=10))
lb1.place(x=10, y=68)
lb2 = tk.Label(window, text='Did not choose the side tables', font=tf.Font(size=10))
lb2.place(x=10, y=90)
bt3 = tk.Button(window, text='合并表格', width=18, height=1, font=tf.Font(size=12), command=join_xlsx)
bt3.place(x=120, y=120)
lb4 = tk.Label(window, text='导出字段:', font=tf.Font(size=10))
lb4.place(x=10, y=160)
COMBOPICKER1 = Combopicker(window, values=['Please read the form', '读取表格'], entrywidth=50)
# COMBOPICKER1.pack(anchor="w")
COMBOPICKER1.place(x=100, y=160)
bt4 = tk.Button(window, text='Export the combined form', width=18, height=1, font=tf.Font(size=12), command=save_xlsx)
bt4.place(x=120, y=200)
lb5 = tk.Label(window, text='No hint', font=tf.Font(size=10))
lb5.place(x=10, y=240)
window.mainloop()
ComBoPicker.py
''' 引用自https://blog.csdn.net/weixin_45774074/article/details/123293411 自定义多选下拉列表 '''
import tkinter.font as tkFont
import tkinter.ttk as ttk
from tkinter import *
class Picker(ttk.Frame):
def __init__(self, master=None,activebackground='#b1dcfb',values=[],entry_wid=None,activeforeground='black', selectbackground='#003eff', selectforeground='white', command=None, borderwidth=1, relief="solid"):
self._selected_item = None
self._values = values
self._entry_wid = entry_wid
self._sel_bg = selectbackground
self._sel_fg = selectforeground
self._act_bg = activebackground
self._act_fg = activeforeground
self._command = command
ttk.Frame.__init__(self, master, borderwidth=borderwidth, relief=relief)
self.bind("<FocusIn>", lambda event:self.event_generate('<<PickerFocusIn>>'))
self.bind("<FocusOut>", lambda event:self.event_generate('<<PickerFocusOut>>'))
self._font = tkFont.Font()
self.dict_checkbutton = {
}
self.dict_checkbutton_var = {
}
self.dict_intvar_item = {
}
for index,item in enumerate(self._values):
self.dict_intvar_item[item] = IntVar()
self.dict_checkbutton[item] = ttk.Checkbutton(self, text = item, variable=self.dict_intvar_item[item],command=lambda ITEM = item:self._command(ITEM))
self.dict_checkbutton[item].grid(row=index, column=0, sticky=NSEW)
self.dict_intvar_item[item].set(0)
class Combopicker(ttk.Entry, Picker):
def __init__(self, master, values= [] ,entryvar=None, entrywidth=None, entrystyle=None, onselect=None,activebackground='#b1dcfb', activeforeground='black', selectbackground='#003eff', selectforeground='white', borderwidth=1, relief="solid"):
self.values=values
if entryvar is not None:
self.entry_var = entryvar
else:
self.entry_var = StringVar()
entry_config = {
}
if entrywidth is not None:
entry_config["width"] = entrywidth
if entrystyle is not None:
entry_config["style"] = entrystyle
ttk.Entry.__init__(self, master, textvariable=self.entry_var, **entry_config, state = "readonly")
self._is_menuoptions_visible = False
self.picker_frame = Picker(self.winfo_toplevel(), values=values,entry_wid = self.entry_var,activebackground=activebackground, activeforeground=activeforeground, selectbackground=selectbackground, selectforeground=selectforeground, command=self._on_selected_check)
self.bind_all("<1>", self._on_click, "+")
self.bind("<Escape>", lambda event: self.hide_picker())
@property
def current_value(self):
try:
value = self.entry_var.get()
return value
except ValueError:
return None
@current_value.setter
def current_value(self, INDEX):
self.entry_var.set(self.values.index(INDEX))
def _on_selected_check(self, SELECTED):
value = []
if self.entry_var.get() != "" and self.entry_var.get() != None:
temp_value = self.entry_var.get()
value = temp_value.split(",")
if str(SELECTED) in value:
value.remove(str(SELECTED))
else:
value.append(str(SELECTED))
value.sort()
temp_value = ""
for index,item in enumerate(value):
if item!= "":
if index != 0:
temp_value += ","
temp_value += str(item)
self.entry_var.set(temp_value)
def _on_click(self, event):
str_widget = str(event.widget)
if str_widget == str(self):
if not self._is_menuoptions_visible:
self.show_picker()
else:
if not str_widget.startswith(str(self.picker_frame)) and self._is_menuoptions_visible:
self.hide_picker()
def show_picker(self):
if not self._is_menuoptions_visible:
self.picker_frame.place(in_=self, relx=0, rely=1, relwidth=1 )
self.picker_frame.lift()
self._is_menuoptions_visible = True
def hide_picker(self):
if self._is_menuoptions_visible:
self.picker_frame.place_forget()
self._is_menuoptions_visible = False
边栏推荐
- 创建型模式 - 抽象工厂模式AbstractFactory
- FastCorrect:语音识别快速纠错模型丨RTC Dev Meetup
- 脂溶性胆固醇-聚乙二醇-叠氮,Cholesterol-PEG-Azide,CLS-PEG-N3
- R语言自学 1 - 向量
- Week 7 CNN Architectures - LeNet-5、AlexNet、VGGNet、GoogLeNet、ResNet
- 停止使用 Storyboards 和 Interface Builder
- mysql根据多字段分组——group by带两个或多个参数
- MySQL 与InnoDB 下的锁做朋友 (四)行锁/记录锁
- 数据库审计 - 网络安全的重要组成部分
- CAS:474922-22-0,DSPE-PEG-MAL,磷脂-聚乙二醇-马来酰亚胺科研试剂供应
猜你喜欢
随机推荐
Rasa 3.x 学习系列- Rasa - Issues 4792 socket debug logs clog up debug feed学习笔记
The CTF command execution subject their thinking
Jmeter secondary development to realize rsa encryption
一个很少见但很有用的SQL功能
工业元宇宙的价值和发展
Controller层代码这么写,简洁又优雅!
【UE5 骨骼动画】全形体IK导致Two Bone IK只能斜着移动,不能平移
WAF WebShell Trojan free to kill
00 -- jieba分词
FastCorrect:语音识别快速纠错模型丨RTC Dev Meetup
如何通过 IDEA 数据库管理工具连接 TDengine?
APT级全面免杀拿Shell
mysql 错误:The driver has not received any packets from the server.
B站回应“HR 称核心用户都是 Loser”:该面试官去年底已被劝退,会吸取教训加强管理
WebShell 木马免杀过WAF
微信小程序实现lot开发09 接入微信登录
qt静态编译出现Project ERROR: Library ‘odbc‘ is not defined
执子手,到永恒
同一份数据,Redis为什么要存两次?
Cholesterol-PEG-Acid,胆固醇-聚乙二醇-羧基保持在干燥、低温环境下