python用tkinter写一个文件对比的小工具,将两个excel文件进行对比,将两个列表差异保存到另一个新建的excel文件中,列表左边为第一个表的不同,右边为第二个表的不同,中间空出三列

发布时间 2023-09-05 14:55:54作者: 我的牛肉面啊

先写文件对比的逻辑代码,包括读取文件,对比文件,将对比出来的差异写入另一个excel文件

1.读取文件,我这里是选取自己需要的不同的列,选定了指定的sheet列表,读者可根据需求更改

def readexcel(file):
    # 打开Excel文件
    workbook = openpyxl.load_workbook(file)

    # 选择指定的Sheet
    sheet = workbook['缺陷列表_1']

    # 选择需要获取的列的列号
    col_numbers = [3, 5, 6]

    # 列名
    titles = ['二级分类', '等级', '爆发行']

    result = []
    # 从第2行开始获取数据
    for i in range(2, sheet.max_row + 1):
        # 每一行的数据
        row_data = []
        for col in col_numbers:
            row_data.append(sheet.cell(row=i, column=col).value)

        # 构建字典
        row_dict = dict(zip(titles, row_data))
        result.append(row_dict)

    return result

2.对比两个文件,获取到两个表对比的不同的地方,组合成元素为字典的列表,需要注意两个文件的长度大小
 1 def comparefile(list1, list2):
 2     list1 = tuple(tuple(item.items()) for item in list1)
 3     list2 = tuple(tuple(item.items()) for item in list2)
 4 
 5     match = len(set(list1) & set(list2))  # 记录重合数
 6     diff = len(set(list1) - set(list2)) + len(set(list2) - set(list1))  # 记录差异数
 7     differ1 = set(list1) - set(list2)  # 记录list1的差异元素
 8     differ2 = set(list2) - set(list1)  # 记录list2的差异元素
 9     differ1_dicts = [dict(item) for item in list(differ1)]
10     differ2_dicts = [dict(item) for item in list(differ2)]
11 
12     print("1111", differ1_dicts, differ2_dicts)
13     print(f"重合数:{match},差异数:{diff}")
14     # differ1=list(differ1)
15     # differ2=list(differ2)
16     return differ1_dicts, differ2_dicts,match,diff

3.将获取到的两个不同的列表写入到新的excel文件中,注意需要判断两个文件是否为空

def writeexcel2(differ1, differ2,filewname):
    global flag
    # 创建一个新的Excel工作簿
    wb = openpyxl.Workbook()
    # 获取正在使用的工作表
    sheet = wb.active
    # 写入differ1
    # 获取所有的key,先判断是否为空
    if  differ1 and differ2:
        keys = differ1[0].keys()
        # 首先将key作为表头写入第一行
        for col_num, key in enumerate(keys, start=1):
            col_letter = openpyxl.utils.get_column_letter(col_num)
            sheet["{0}1".format(col_letter)] = key
        # 依次写入每一行数据
        for row_num, row_data in enumerate(differ1, start=2):
            for col_num, key in enumerate(keys, start=1):
                col_letter = openpyxl.utils.get_column_letter(col_num)
                if type(key) != str:  # 添加判断语句,确保key是字符串类型
                    key = str(key)
                sheet["{0}{1}".format(col_letter, row_num)] = row_data[key]
            # 差异表1和差异表2之间有两个空列,写入空列数据
            sheet.cell(row=row_num, column=len(keys) + 3, value="")
            # 为当前行的所有单元格添加淡蓝色填充
            for col_num in range(1, len(keys) + 1):
                col_letter = openpyxl.utils.get_column_letter(col_num)
                sheet["{0}{1}".format(col_letter, row_num)].fill = PatternFill(start_color='ADD8E6',
                                                                           end_color='ADD8E6',
                                                                           fill_type='solid')
        # 写入differ2
        # 得到所有的key
        # 首先把key作为表头写入第一行
        for col_num, key in enumerate(keys,start=len(differ1[0].keys()) + 3):
            col_letter = openpyxl.utils.get_column_letter(col_num)
            sheet["{0}1".format(col_letter)] = key
        # 依次写入每一行的数据
        for row_num, row_data in enumerate(differ2, start=2):
            for col_num, key in enumerate(keys, start=1):
                col_letter = openpyxl.utils.get_column_letter(col_num+ len(differ1[0].keys()) + 2)
                if type(key) != str:  # 添加判断语句,确保key是字符串类型
                    key = str(key)
                sheet["{0}{1}".format(col_letter, row_num)] = row_data[key]
                # 为当前行的所有单元格添加淡黄色填充
                for col_num in range(len(differ1[0].keys()) + 3, len(keys) + len(differ1[0].keys()) + 4):
                    col_letter = openpyxl.utils.get_column_letter(col_num)
                    sheet["{0}{1}".format(col_letter, row_num)].fill = PatternFill(start_color='FFFFE0',
                                                                                   end_color='FFFFE0',
                                                                                   fill_type='solid')
    #如果differ1不为空,differ2为空
    elif differ1 and not differ2:
        keys = differ1[0].keys()
        # 首先将key作为表头写入第一行
        for col_num, key in enumerate(keys, start=1):
            col_letter = openpyxl.utils.get_column_letter(col_num)
            sheet["{0}1".format(col_letter)] = key
        # 依次写入每一行数据
        for row_num, row_data in enumerate(differ1, start=2):
            for col_num, key in enumerate(keys, start=1):
                col_letter = openpyxl.utils.get_column_letter(col_num)
                if type(key) != str:  # 添加判断语句,确保key是字符串类型
                    key = str(key)
                sheet["{0}{1}".format(col_letter, row_num)] = row_data[key]
            # 差异表1和差异表2之间有两个空列,写入空列数据
            sheet.cell(row=row_num, column=len(keys) + 3, value="")

            # 为当前行的所有单元格添加淡蓝色填充
            for col_num in range(1, len(keys) + 1):
                col_letter = openpyxl.utils.get_column_letter(col_num)
                sheet["{0}{1}".format(col_letter, row_num)].fill = PatternFill(start_color='ADD8E6',
                                                                               end_color='ADD8E6',
                                                                               fill_type='solid')

    #如果differ1为空。differ2不为空
    elif len(differ2)!=0 and len(differ1)==0:
        keys = differ2[0].keys()
        # 首先将key作为表头写入第一行
        for col_num, key in enumerate(keys, start=1):
            col_letter = openpyxl.utils.get_column_letter(col_num)
            sheet["{0}1".format(col_letter)] = key
        # 依次写入每一行数据
        for row_num, row_data in enumerate(differ2, start=2):
            for col_num, key in enumerate(keys, start=1):
                col_letter = openpyxl.utils.get_column_letter(col_num)
                if type(key) != str:  # 添加判断语句,确保key是字符串类型
                    key = str(key)
                sheet["{0}{1}".format(col_letter, row_num)] = row_data[key]
            # # 差异表1和差异表2之间有两个空列,写入空列数据
            sheet.cell(row=row_num, column=len(keys) + 3, value="")
            # 为当前行的所有单元格添加淡黄色填充
            for col_num in range(1, len(keys) + 1):
                col_letter = openpyxl.utils.get_column_letter(col_num)
                sheet["{0}{1}".format(col_letter, row_num)].fill = PatternFill(start_color='FFFFE0',
                                                                               end_color='FFFFE0',
                                                                               fill_type='solid')

    #两个列表都为空
    else:
        print("表1和表2数据完全重合")

    # 保存Excel工作簿
    wb.save(filewname)
    flag = True
    print("保存差异值到excel文件完成")
    return flag

以上就是文件对比的逻辑代码。现在我们需要使用tkinter构建前端小工具

def FileOpen():
#文件对话框,能打开写死的文件框
    return_value = tkinter.filedialog.askopenfilename()
    if return_value.strip()!=" ":
        filename1.set(return_value)
    else:
        print("未上传所需文件")
    #直接打开文件选择框
    print(type(return_value),return_value)
def FileOpen2():
#文件对话框,能打开写死的文件框
    return_value = tkinter.filedialog.askopenfilename()
    if return_value.strip()!=" ":
        filename2.set(return_value)
    else:
        print("未上传所需文件")
    #直接打开文件选择框
    print(type(return_value),return_value)
def FileSave():
    #设置保存文件,并返回文件名,指定文件名后缀为“.xls
    r=tkinter.filedialog.asksaveasfilename(title="保存文件",defaultextension='.xls'
                                           # initialdir="E:\Tools\files",
                                           # initialfile='test.py'
                                           )
    if r.strip()!=' ':
        filewname.set(r)
    else:
        print("未选择需要保存的文件")
    print(r)

root = Tk()  # 创建主窗口【必要步骤】
# 将该窗口赋值给root变量,方便后续使用
root.title('主窗口')
root.geometry('960x480+150+100')#设置窗口大小及位置
root.wm_attributes('-alpha')#设置透明度为0.7
root.resizable(1,1)#窗口大小不可改变两个布尔值分别代表窗口的长和宽是否可改变(可以用0和1代替布尔值)

filename1 = tkinter.StringVar()
filename2=tkinter.StringVar()
filewname=tkinter.StringVar()
# toplevel=Toplevel(root)
# toplevel.title('子窗口')
#打开文件
#Entry:文本框输入框,Label:标签熟悉
def ui():
    tkinter.Label(root, text='选择第一个文件').grid(row=1, column=1, padx=5, pady=7)
    #第一个输入框
    filename1path=tkinter.Entry(root, textvariable=filename1, width=40 )
    filename1path.grid(row=1, column=2, padx=5, pady=5)
    b1=Button(root,relief='groove',activebackground='pink',bg='lightblue',overrelief='ridge',text='上传文件',command=FileOpen).grid(row=1, column=3, padx=5, pady=5)#创建按钮
    # b1.pack(side="left")

    tkinter.Label(root, text='选择第二个文件').grid(row=2, column=1, padx=5, pady=5)
    #第二个输入框
    filename2path=tkinter.Entry(root, textvariable=filename2, width=40 )
    filename2path.grid(row=2, column=2, padx=5, pady=5)
    b2=Button(root,relief='groove',activebackground='pink',bg='lightblue',overrelief='ridge',text='上传文件',command=FileOpen2).grid(row=2, column=3, padx=5, pady=5)
    # b2.pack(side="left")

    # b.place(width=100,height=30,x=150,y=200)#防止按钮
    tkinter.Label(root, text='保存文件').grid(row=5, column=1, padx=5, pady=5)
    #第三个输入框
    filewnamepath=tkinter.Entry(root, textvariable=filewname, width=40 )
    filewnamepath.grid(row=5, column=2, padx=5, pady=5)
    b3=Button(root,text='保存文件',command=FileSave,relief='groove',activebackground='pink',bg='orange',overrelief='ridge',).grid(row=5, column=3, padx=5, pady=5)
    # b3.pack(side="left")

    tkinter.Button(root,text="开始对比",activebackground='pink',bg='lightblue',overrelief='ridge',command=lambda :contrast_button_clicked(filename1path.get(),filename2path.get(),filewnamepath.get())).grid(row=6, column=3, padx=5, pady=5)

    #窗口主循环
    root.mainloop()  # 主窗口进入消息事件循环【必要步骤】放在最后

 

tkinter界面和逻辑都构建完成,就是将以上的函数组合起来,主函数为main

def main(filename1path,filename2path,filewnamepath):
    list1 = readexcel(filename1path)
    list2 = readexcel(filename2path)
    print(list1)
    print(list2)
    differ1, differ2,match,diff = comparefile(list1, list2)
    flag=writeexcel2(differ1, differ2,filewnamepath)
    return match,diff,flag

main函数的返回值需要显示在tkinker小工具的界面上,于是

def contrast_button_clicked(filename1path, filename2path, filewnamepath):
    match, diff,flag = main(filename1path, filename2path, filewnamepath)
    if flag:
        tkinter.messagebox.showinfo("提示", "对比成功!共有"+str(match)+"组数据重合,"+"共有" +str(diff)+"组数据不一致,详细情况请到"+ filewnamepath + "文件查看")
    else:
        tkinter.messagebox.showinfo("提示", "对比失败!请检查输入路径是否正确")

最后

if __name__ == '__main__':
    ui()

整体的代码为

 

import tkinter.filedialog
from tkinter import messagebox
from tkinter import *  # 导入tkinter模块【必要步骤】
import xlrd
import xlwt
import openpyxl
from openpyxl.styles import PatternFill


def FileOpen():
#文件对话框,能打开写死的文件框
    return_value = tkinter.filedialog.askopenfilename()
    if return_value.strip()!=" ":
        filename1.set(return_value)
    else:
        print("未上传所需文件")
    #直接打开文件选择框
    print(type(return_value),return_value)
def FileOpen2():
#文件对话框,能打开写死的文件框
    return_value = tkinter.filedialog.askopenfilename()
    if return_value.strip()!=" ":
        filename2.set(return_value)
    else:
        print("未上传所需文件")
    #直接打开文件选择框
    print(type(return_value),return_value)
def FileSave():
    #设置保存文件,并返回文件名,指定文件名后缀为“.xls
    r=tkinter.filedialog.asksaveasfilename(title="保存文件",defaultextension='.xls'
                                           # initialdir="E:\Tools\files",
                                           # initialfile='test.py'
                                           )
    if r.strip()!=' ':
        filewname.set(r)
    else:
        print("未选择需要保存的文件")
    print(r)


root = Tk()  # 创建主窗口【必要步骤】
# 将该窗口赋值给root变量,方便后续使用
root.title('主窗口')
root.geometry('960x480+150+100')#设置窗口大小及位置
root.wm_attributes('-alpha')#设置透明度为0.7
root.resizable(1,1)#窗口大小不可改变两个布尔值分别代表窗口的长和宽是否可改变(可以用0和1代替布尔值)

filename1 = tkinter.StringVar()
filename2=tkinter.StringVar()
filewname=tkinter.StringVar()
# toplevel=Toplevel(root)
# toplevel.title('子窗口')
#打开文件
#Entry:文本框输入框,Label:标签熟悉
def ui():
    tkinter.Label(root, text='选择第一个文件').grid(row=1, column=1, padx=5, pady=7)
    #第一个输入框
    filename1path=tkinter.Entry(root, textvariable=filename1, width=40 )
    filename1path.grid(row=1, column=2, padx=5, pady=5)
    b1=Button(root,relief='groove',activebackground='pink',bg='lightblue',overrelief='ridge',text='上传文件',command=FileOpen).grid(row=1, column=3, padx=5, pady=5)#创建按钮
    # b1.pack(side="left")

    tkinter.Label(root, text='选择第二个文件').grid(row=2, column=1, padx=5, pady=5)
    #第二个输入框
    filename2path=tkinter.Entry(root, textvariable=filename2, width=40 )
    filename2path.grid(row=2, column=2, padx=5, pady=5)
    b2=Button(root,relief='groove',activebackground='pink',bg='lightblue',overrelief='ridge',text='上传文件',command=FileOpen2).grid(row=2, column=3, padx=5, pady=5)
    # b2.pack(side="left")

    # b.place(width=100,height=30,x=150,y=200)#防止按钮
    tkinter.Label(root, text='保存文件').grid(row=5, column=1, padx=5, pady=5)
    #第三个输入框
    filewnamepath=tkinter.Entry(root, textvariable=filewname, width=40 )
    filewnamepath.grid(row=5, column=2, padx=5, pady=5)
    b3=Button(root,text='保存文件',command=FileSave,relief='groove',activebackground='pink',bg='orange',overrelief='ridge',).grid(row=5, column=3, padx=5, pady=5)
    # b3.pack(side="left")

    tkinter.Button(root,text="开始对比",activebackground='pink',bg='lightblue',overrelief='ridge',command=lambda :contrast_button_clicked(filename1path.get(),filename2path.get(),filewnamepath.get())).grid(row=6, column=3, padx=5, pady=5)

    #窗口主循环
    root.mainloop()  # 主窗口进入消息事件循环【必要步骤】放在最后

def contrast_button_clicked(filename1path, filename2path, filewnamepath):
    match, diff,flag = main(filename1path, filename2path, filewnamepath)
    if flag:
        tkinter.messagebox.showinfo("提示", "对比成功!共有"+str(match)+"组数据重合,"+"共有" +str(diff)+"组数据不一致,详细情况请到"+ filewnamepath + "文件查看")
    else:
        tkinter.messagebox.showinfo("提示", "对比失败!请检查输入路径是否正确")




def readexcel(file):
    # 打开Excel文件
    workbook = openpyxl.load_workbook(file)
    # 选择指定的Sheet
    sheet = workbook['缺陷列表_1']
    # 选择需要获取的列的列号
    col_numbers = [3, 5, 6]
    # 列名
    titles = ['二级分类', '等级', '爆发行']
    result = []
    # 从第2行开始获取数据
    for i in range(2, sheet.max_row + 1):
        # 每一行的数据
        row_data = []
        for col in col_numbers:
            row_data.append(sheet.cell(row=i, column=col).value)
        # 构建字典
        row_dict = dict(zip(titles, row_data))
        result.append(row_dict)
    return result

def comparefile(list1, list2):
    list1 = tuple(tuple(item.items()) for item in list1)
    list2 = tuple(tuple(item.items()) for item in list2)
    match = len(set(list1) & set(list2))  # 记录重合数
    diff = len(set(list1) - set(list2)) + len(set(list2) - set(list1))  # 记录差异数
    differ1 = set(list1) - set(list2)  # 记录list1的差异元素
    differ2 = set(list2) - set(list1)  # 记录list2的差异元素
    differ1_dicts = [dict(item) for item in list(differ1)]
    differ2_dicts = [dict(item) for item in list(differ2)]

    print("1111", differ1_dicts, differ2_dicts)
    print(f"重合数:{match},差异数:{diff}")
    # differ1=list(differ1)
    # differ2=list(differ2)
    return differ1_dicts, differ2_dicts,match,diff

def writeexcel2(differ1, differ2,filewname):
    global flag
    # 创建一个新的Excel工作簿
    wb = openpyxl.Workbook()
    # 获取正在使用的工作表
    sheet = wb.active
    # 写入differ1
    # 获取所有的key,先判断是否为空
    if  differ1 and differ2:
        keys = differ1[0].keys()
        # 首先将key作为表头写入第一行
        for col_num, key in enumerate(keys, start=1):
            col_letter = openpyxl.utils.get_column_letter(col_num)
            sheet["{0}1".format(col_letter)] = key
        # 依次写入每一行数据
        for row_num, row_data in enumerate(differ1, start=2):
            for col_num, key in enumerate(keys, start=1):
                col_letter = openpyxl.utils.get_column_letter(col_num)
                if type(key) != str:  # 添加判断语句,确保key是字符串类型
                    key = str(key)
                sheet["{0}{1}".format(col_letter, row_num)] = row_data[key]
            # 差异表1和差异表2之间有两个空列,写入空列数据
            sheet.cell(row=row_num, column=len(keys) + 3, value="")

            # 为当前行的所有单元格添加淡蓝色填充
            for col_num in range(1, len(keys) + 1):
                col_letter = openpyxl.utils.get_column_letter(col_num)
                sheet["{0}{1}".format(col_letter, row_num)].fill = PatternFill(start_color='ADD8E6',
                                                                           end_color='ADD8E6',
                                                                           fill_type='solid')
        # 写入differ2
        # 得到所有的key
        # 首先把key作为表头写入第一行
        for col_num, key in enumerate(keys,start=len(differ1[0].keys()) + 3):
            col_letter = openpyxl.utils.get_column_letter(col_num)
            sheet["{0}1".format(col_letter)] = key
        # 依次写入每一行的数据
        for row_num, row_data in enumerate(differ2, start=2):
            for col_num, key in enumerate(keys, start=1):
                col_letter = openpyxl.utils.get_column_letter(col_num+ len(differ1[0].keys()) + 2)
                if type(key) != str:  # 添加判断语句,确保key是字符串类型
                    key = str(key)
                sheet["{0}{1}".format(col_letter, row_num)] = row_data[key]
                # 为当前行的所有单元格添加淡黄色填充
                for col_num in range(len(differ1[0].keys()) + 3, len(keys) + len(differ1[0].keys()) + 4):
                    col_letter = openpyxl.utils.get_column_letter(col_num)
                    sheet["{0}{1}".format(col_letter, row_num)].fill = PatternFill(start_color='FFFFE0',
                                                                                   end_color='FFFFE0',
                                                                                   fill_type='solid')
    #如果differ1不为空,differ2为空
    elif differ1 and not differ2:
        keys = differ1[0].keys()
        # 首先将key作为表头写入第一行
        for col_num, key in enumerate(keys, start=1):
            col_letter = openpyxl.utils.get_column_letter(col_num)
            sheet["{0}1".format(col_letter)] = key
        # 依次写入每一行数据
        for row_num, row_data in enumerate(differ1, start=2):
            for col_num, key in enumerate(keys, start=1):
                col_letter = openpyxl.utils.get_column_letter(col_num)
                if type(key) != str:  # 添加判断语句,确保key是字符串类型
                    key = str(key)
                sheet["{0}{1}".format(col_letter, row_num)] = row_data[key]
            # 差异表1和差异表2之间有两个空列,写入空列数据
            sheet.cell(row=row_num, column=len(keys) + 3, value="")

            # 为当前行的所有单元格添加淡蓝色填充
            for col_num in range(1, len(keys) + 1):
                col_letter = openpyxl.utils.get_column_letter(col_num)
                sheet["{0}{1}".format(col_letter, row_num)].fill = PatternFill(start_color='ADD8E6',
                                                                               end_color='ADD8E6',
                                                                               fill_type='solid')

    #如果differ1为空。differ2不为空
    elif len(differ2)!=0 and len(differ1)==0:
        keys = differ2[0].keys()
        # 首先将key作为表头写入第一行
        for col_num, key in enumerate(keys, start=1):
            col_letter = openpyxl.utils.get_column_letter(col_num)
            sheet["{0}1".format(col_letter)] = key
        # 依次写入每一行数据
        for row_num, row_data in enumerate(differ2, start=2):
            for col_num, key in enumerate(keys, start=1):
                col_letter = openpyxl.utils.get_column_letter(col_num)
                if type(key) != str:  # 添加判断语句,确保key是字符串类型
                    key = str(key)
                sheet["{0}{1}".format(col_letter, row_num)] = row_data[key]
            # # 差异表1和差异表2之间有两个空列,写入空列数据
            sheet.cell(row=row_num, column=len(keys) + 3, value="")
            # 为当前行的所有单元格添加淡黄色填充
            for col_num in range(1, len(keys) + 1):
                col_letter = openpyxl.utils.get_column_letter(col_num)
                sheet["{0}{1}".format(col_letter, row_num)].fill = PatternFill(start_color='FFFFE0',
                                                                               end_color='FFFFE0',
                                                                               fill_type='solid')

    #两个列表都为空
    else:
        print("表1和表2数据完全重合")

    # 保存Excel工作簿
    wb.save(filewname)
    flag = True
    print("保存差异值到excel文件完成")
    return flag
def main(filename1path,filename2path,filewnamepath):
    # file1 = filename1.get()
    # file2 = filename2.get()
    # resultfile = filewname.get()
    list1 = readexcel(filename1path)
    list2 = readexcel(filename2path)
    print(list1)
    print(list2)
    differ1, differ2,match,diff = comparefile(list1, list2)
    flag=writeexcel2(differ1, differ2,filewnamepath)
    # print("flag",flag)
    return match,diff,flag


if __name__ == '__main__':
    ui()

运行的tkinter界面为  

看右半边

最后对比的结果的界面为