基于 Python的 Excel 文件差异对比工具
- 2026-09-21 17:40:57
基于 Python的 Excel 文件差异对比工具


基于 Tkinter 的 Excel 文件差异对比工具,核心要求是通过 pandas.merge 外连接实现数据比对、用 openpyxl 给差异单元格标红、最终生成带样式的变更报告和数据汇总统计。



下面为你提供一个完整、可直接运行的实现方案,包含所有核心功能。
前置准备
首先安装所需依赖库,打开终端执行以下命令:
pip install tkinter pandas openpyxl注意:tkinter 在 Python 3 中通常自带,若缺失请根据你的系统单独安装(Windows 一般自带,Linux 可执行
sudo apt install python3-tk)。
完整实现代码
import tkinter as tkfrom tkinter import filedialog, messageboximport pandas as pdfrom openpyxl import load_workbookfrom openpyxl.styles import PatternFillfrom datetime import datetimeclassExcelDiffTool:def__init__(self, root):"""初始化GUI界面和变量""" self.root = root self.root.title("Excel 数据差异对比工具") self.root.geometry("600x300")# 存储两个Excel文件路径 self.file1_path = tk.StringVar() self.file2_path = tk.StringVar()# 构建GUI控件 self._build_gui()def_build_gui(self):"""构建Tkinter图形界面"""# 第一个文件选择区域 frame1 = tk.Frame(self.root, pady=10) frame1.pack(fill=tk.X, padx=20) tk.Label(frame1, text="原始Excel文件:").pack(side=tk.LEFT) tk.Entry(frame1, textvariable=self.file1_path, width=50).pack(side=tk.LEFT, padx=10) tk.Button(frame1, text="浏览", command=lambda: self._select_file(self.file1_path)).pack(side=tk.LEFT)# 第二个文件选择区域 frame2 = tk.Frame(self.root, pady=10) frame2.pack(fill=tk.X, padx=20) tk.Label(frame2, text="对比Excel文件:").pack(side=tk.LEFT) tk.Entry(frame2, textvariable=self.file2_path, width=50).pack(side=tk.LEFT, padx=10) tk.Button(frame2, text="浏览", command=lambda: self._select_file(self.file2_path)).pack(side=tk.LEFT)# 执行对比按钮 tk.Button(self.root, text="开始差异对比", command=self._execute_excel_diff, bg="#4CAF50", fg="white", padx=10, pady=5).pack(pady=30)def_select_file(self, var):"""打开文件选择对话框,选择Excel文件""" file_path = filedialog.askopenfilename( title="选择Excel文件", filetypes=(("Excel文件", "*.xlsx;*.xls"), ("所有文件", "*.*")) )if file_path: var.set(file_path)def_execute_excel_diff(self):"""核心执行逻辑:读取Excel、数据比对、标红差异、生成报告""" file1 = self.file1_path.get() file2 = self.file2_path.get()# 校验文件路径ifnot file1 ornot file2: messagebox.showwarning("警告", "请先选择两个Excel文件!")returnif file1 == file2: messagebox.showwarning("警告", "请选择两个不同的Excel文件!")returntry:# 1. 读取Excel数据(默认读取第一个工作表) df1 = pd.read_excel(file1, engine="openpyxl") df2 = pd.read_excel(file2, engine="openpyxl")# 校验数据是否为空if df1.empty or df2.empty: messagebox.showwarning("警告", "所选Excel文件中存在空数据!")return# 2. 用pandas.merge外连接比对数据(默认以所有列作为关联键,可根据需求修改)# 先添加来源标识列 df1["_data_source_"] = "原始文件" df2["_data_source_"] = "对比文件"# 外连接比对 merged_df = pd.merge(df1, df2, how="outer", indicator=True, suffixes=("_原始", "_对比"))# 3. 生成差异数据、变更报告和汇总统计 diff_result, summary_stats = self._analyze_diff_data(merged_df)# 4. 保存变更报告并给差异单元格标红 report_filename = f"Excel差异变更报告_{datetime.now().strftime('%Y%m%d_%H%M%S')}.xlsx" self._save_diff_report_with_style(diff_result, report_filename, df1.columns)# 5. 弹出完成提示,展示汇总统计 summary_info = "\n".join([f"{k}:{v}"for k, v in summary_stats.items()]) messagebox.showinfo("完成", f"差异对比已完成!\n\n汇总统计:\n{summary_info}\n\n变更报告已保存为:\n{report_filename}")except Exception as e: messagebox.showerror("错误", f"执行过程中出现异常:\n{str(e)}")def_analyze_diff_data(self, merged_df):"""分析比对结果,提取差异数据和生成汇总统计"""# 提取差异数据(仅保留非"both"的记录,即仅在原始文件/仅在对比文件/数据不一致) diff_df = merged_df[merged_df["_merge"] != "both"].copy()# 汇总统计 summary_stats = {"原始文件数据行数": len(merged_df[merged_df["_merge"] == "left_only"]) + len(merged_df[merged_df["_merge"] == "both"]),"对比文件数据行数": len(merged_df[merged_df["_merge"] == "right_only"]) + len(merged_df[merged_df["_merge"] == "both"]),"仅在原始文件存在的行数": len(merged_df[merged_df["_merge"] == "left_only"]),"仅在对比文件存在的行数": len(merged_df[merged_df["_merge"] == "right_only"]),"双方共有但数据不一致的行数": len(merged_df[merged_df["_merge"] == "both"]) - len(merged_df[merged_df.duplicated()]),"总差异行数": len(diff_df) }# 清理辅助列(可选,根据需求保留) diff_df = diff_df.drop(columns=["_merge"], errors="ignore")return diff_df, summary_statsdef_save_diff_report_with_style(self, diff_df, filename, original_columns):"""保存变更报告,并用openpyxl给差异单元格填充红色背景"""# 1. 先将差异数据保存为Excel文件 diff_df.to_excel(filename, index=False, engine="openpyxl")# 2. 用openpyxl加载文件,准备设置单元格样式 wb = load_workbook(filename) ws = wb.active# 定义红色填充样式(差异单元格背景) red_fill = PatternFill(start_color="FFFF0000", end_color="FFFF0000", fill_type="solid")# 3. 遍历单元格,标记差异(核心:对比原始列和对比列的数值)# 获取所有带后缀的列名 original_cols = [col + "_原始"for col in original_columns if col + "_原始"in diff_df.columns] compare_cols = [col + "_对比"for col in original_columns if col + "_对比"in diff_df.columns]# 列名映射(原始列 ↔ 对比列) col_pair = list(zip(original_cols, compare_cols))# 遍历数据行(从第2行开始,第1行是表头)for row in range(2, ws.max_row + 1):# 遍历每一对原始/对比列for orig_col, comp_col in col_pair:# 获取列的字母标识(如A、B、C...) orig_col_letter = ws[orig_col].column_letter if orig_col in ws elseNone comp_col_letter = ws[comp_col].column_letter if comp_col in ws elseNoneif orig_col_letter and comp_col_letter:# 获取单元格值 cell_orig = ws[f"{orig_col_letter}{row}"] cell_comp = ws[f"{comp_col_letter}{row}"]# 标记差异:值不相等且都不为空(或其中一个为空)if cell_orig.value != cell_comp.value: cell_orig.fill = red_fill cell_comp.fill = red_fill# 4. 保存带样式的Excel文件 wb.save(filename)if __name__ == "__main__": root = tk.Tk() app = ExcelDiffTool(root) root.mainloop()核心功能说明
1. GUI 界面功能
提供两个文件选择框,支持浏览选择 .xlsx/.xls格式的 Excel 文件输入校验,防止未选择文件或选择相同文件 友好的提示弹窗(成功、警告、错误)
2. 数据比对核心
使用 pd.read_excel读取 Excel 数据,指定engine="openpyxl"兼容.xlsx格式给两个 DataFrame 添加来源标识,通过 pd.merge(how="outer", indicator=True)实现外连接比对_merge列标记数据来源:left_only(仅原始文件)、right_only(仅对比文件)、both(双方共有)
3. 差异单元格标红
先将差异数据保存为 Excel 文件,再用 openpyxl加载文件进行样式修改定义 PatternFill红色填充样式,遍历原始列和对比列的对应单元格只要单元格值不相等,就给两个单元格都标红,清晰展示差异
4. 汇总统计与变更报告
统计核心数据:原始/对比文件行数、仅单方存在的行数、总差异行数等 生成带时间戳的变更报告文件名,避免重复覆盖 报告中保留完整差异数据,差异单元格红色高亮,便于查看
使用方法
运行上述代码,弹出 GUI 界面 点击「浏览」分别选择两个需要对比的 Excel 文件(建议列结构一致,便于精准比对) 点击「开始差异对比」,等待执行完成 执行完成后,会在当前脚本运行目录下生成带时间戳的差异变更报告 Excel 文件 查看报告:差异单元格已标红,同时弹窗展示汇总统计信息
注意事项
该工具默认读取 Excel 文件的第一个工作表,若需要指定工作表,可修改 pd.read_excel中的sheet_name参数(如sheet_name="Sheet2")数据比对默认以所有列作为关联键,若需要指定特定关联列(如主键 ID),可修改 pd.merge中的on参数(如on=["ID", "姓名"])仅支持 .xlsx格式文件,.xls格式需要额外安装xlrd库(pip install xlrd==1.2.0)若 Excel 文件较大,执行时间会相应增加,建议避免对比超大文件
总结
该工具通过 Tkinter实现可视化文件选择,核心依赖pandas.merge外连接完成数据比对,openpyxl实现差异单元格标红。运行后自动生成带时间戳的变更报告,同时弹窗返回汇总统计,满足 Excel 差异对比的核心需求。 可根据实际业务场景,调整关联键( on参数)、工作表(sheet_name参数),适配不同格式的 Excel 数据。
本文来自网友投稿或网络内容,如有侵犯您的权益请联系我们删除,联系邮箱:wyl860211@qq.com 。