当前位置:网站首页>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
边栏推荐
猜你喜欢

1 - vector R language self-study

No-code development platform form styling steps introductory course

FastCorrect:语音识别快速纠错模型丨RTC Dev Meetup
![[论文总结] 深度学习在农业领域应用论文笔记10](/img/e8/0ba741980495cd81ca30bf269d1111.jpg)
[论文总结] 深度学习在农业领域应用论文笔记10

微信小程序(一)

分库分表索引设计:二级索引、全局索引的最佳设计实践

在软件测试行业近20年的我,再来和大家谈谈今日的软件测试

VMware workstation program starts slowly

IDEA 重复代码的黄色波浪线取消设置
思源笔记 本地存储无使用第三方同步盘,突然打不开文件。
随机推荐
B站回应“HR 称核心用户都是 Loser”:该面试官去年底已被劝退,会吸取教训加强管理
Image recognition from zero to write DNF script key points
非关系型数据库MongoDB简介和部署
合并两个excel表格工具
记一次mysql查询慢的优化历程
漫画:怎么证明sleep不释放锁,而wait释放锁?
基于奇异谱分析法和长短时记忆网络组合模型的滑坡位移预测
程序员如何优雅地解决线上问题?
# DWD层及DIM层构建## ,220801 ,
最近公共祖先(LCA)学习笔记 | P3379 【模板】最近公共祖先(LCA)题解
创建型模式 - 简单工厂模式StaticFactoryMethod
21天学习挑战赛(1)设备树的由来
工业元宇宙的价值和发展
我们来浅谈代码语言的魅力
2022山东国际青少年眼睛健康产业展会,视力健康展,眼视光展
mPEG-Cholesterol,mPEG-CLS,甲氧基-聚乙二醇-胆固醇可用于脂质体制备
【代码扫描修复】MD5加密弱HASH漏洞
【斯坦福计网CS144项目】Lab5: NetworkInterface
APT级全面免杀拿Shell
基于STM32的FLASH读写实验含代码(HAL库)