当前位置:网站首页>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
边栏推荐
猜你喜欢
随机推荐
买母婴产品先来京东“券民空间站”抢券!大牌好物低至5折
HCIP(17)
无代码开发平台数据ID入门教程
Swift中的类型相关内容
MySQL最大建议行数2000w, 靠谱吗?
IDEA 重复代码的黄色波浪线取消设置
airflow db init 报错
MDL 内存描述符链表
程序员如何优雅地解决线上问题?
vant-swipe自适应图片高度+图片预览
2022中国眼博会,山东眼健康展,视力矫正仪器展,护眼产品展
msys2下载地址
创建型模式 - 单例模式Singleton
Based on two levels of decomposition and the length of the memory network multi-step combined forecasting model of short-term wind speed
CTF命令执行题目解题思路
I have been in the software testing industry for nearly 20 years, let me talk to you about today's software testing
CAS:1445723-73-8,DSPE-PEG-NHS,磷脂-聚乙二醇-活性酯两亲性脂质PEG共轭物
IDO预售代币合约系统开发技术说明及源码分析
语音合成模型小抄(1)
Token、Redis实现单点登录