Python Excel表格数据对比工具

【Excel对比工具】提升工作效率的神奇助手:基于PyQt5和Pandas的文件数据对比应用

相关资源文件已经打包成EXE文件,可双击直接运行程序,且文章末尾已附上相关源码,以供大家学习交流,博主主页还有更多Python相关程序案例,秉着开源精神的想法,望大家喜欢,点个关注不迷路!!!

在日常的数据处理与分析工作中,我们经常需要对比两个 Excel 文件中的数据。这种操作看似简单,但如果手动操作,不仅容易出错,而且非常耗时。今天,我们将深入探讨如何通过 Python 和 PyQt5 结合 pandas 库,快速实现一个高效、自动化的 Excel 数据对比工具。本文将详细介绍该工具的功能和使用方法,并探讨其潜在的扩展性。
在这里插入图片描述

1.概述

数据对比是数据处理中的一项基础工作,特别是在审计、报告、数据验证等任务中,通常需要确保两个数据源的内容一致。在实际的业务操作中,Excel 文件由于其简便易用、兼容性强,成为了大量数据存储的首选。然而,手动对比 Excel 文件往往繁琐且容易出现差错,尤其是在数据量较大的情况下。为了提升工作效率,本文基于 Python 中的 PyQt5 和 pandas 库,开发了一个简洁易用的 Excel 数据对比工具,能够高效地比较两个 Excel 文件中的数据差异。

1.1技术栈

  • PyQt5:用于构建桌面 GUI(图形用户界面),提供友好的用户交互界面。
  • pandas:处理 Excel 文件,进行数据对比。
  • openpyxl:用来处理 Excel 文件的写入和样式设置,导出比较结果。
  • QSS:通过自定义样式表美化界面,提升用户体验。

2.功能使用

2.1. 界面介绍

该工具的界面简单直观,包含以下主要部分:

  • 文件选择:用户可以选择需要比较的两个 Excel 文件。
  • Sheet 选择:加载 Excel 文件后,用户可以选择要比较的工作表。
  • 列选择:用户选择要进行对比的列,可以灵活选择不同列的数据进行比对。
  • 对比结果表格:展示对比结果,包括左侧数据、右侧数据、匹配状态和内容对比。若数据不匹配,相关行会高亮显示。
  • 操作按钮:用户可以点击按钮执行对比操作、导出结果、重置界面和退出程序。

2. 2 文件加载与工作表选择

首先,用户通过点击“打开”按钮选择两个 Excel 文件。文件选择完成后,应用会自动读取并展示文件中的所有工作表名称,用户可以从下拉框中选择对应的工作表。

file_path, _ = QFileDialog.getOpenFileName(self, "选择 Excel 文件", "", "Excel 文件 (*.xlsx *.xls)")
  1. 列选择与数据对比
    用户可以选择要对比的列。点击“开始对比”按钮后,应用会依照选择的列名对比两个工作表中的数据。如果两列数据一致,表格中会显示“✔”标记;若不一致,则显示“✘”标记,并高亮不匹配的行,详细展示差异内容。
left_value = str(df_left[left_col].iloc[i])
right_value = str(df_right[right_col].iloc[i])
match = "✔" if left_value == right_value else "✘"
  1. 导出结果
    用户对比完成后,可以通过“导出结果”按钮将对比结果保存为新的 Excel 文件。保存时,程序会自动高亮不匹配的数据行,并将所有对比信息写入到新文件中,便于后续查看与分析。
ws.append([left_data, right_data, match_status, compare_info])
  1. 重置与退出功能
    程序提供了“重置界面”按钮,用于清空当前选项和对比结果,方便用户重新开始操作。同时,“退出程序”按钮可以关闭应用。

代码实现
上述功能的实现主要依赖于 PyQt5 和 pandas 库。以下是部分关键代码片段:

文件加载与数据读取

def load_file(self, side):file_path, _ = QFileDialog.getOpenFileName(self, "选择 Excel 文件", "", "Excel 文件 (*.xlsx *.xls)")if not file_path:return# 选择文件后更新界面if side == "left":self.left_file = file_pathelse:self.right_file = file_path# 加载工作表名称try:sheets = pd.ExcelFile(file_path).sheet_namesif side == "left":self.left_sheet.addItems(sheets)else:self.right_sheet.addItems(sheets)except Exception as e:QMessageBox.warning(self, "错误", f"无法读取 Excel 文件: {e}")

数据对比与结果展示

def compare_data(self):left_col = self.left_column.currentText()right_col = self.right_column.currentText()# 读取数据df_left = pd.read_excel(self.left_file, sheet_name=self.left_sheet.currentText())df_right = pd.read_excel(self.right_file, sheet_name=self.right_sheet.currentText())# 对比并更新表格for i in range(min(len(df_left), len(df_right))):left_value = str(df_left[left_col].iloc[i])right_value = str(df_right[right_col].iloc[i])match = "✔" if left_value == right_value else "✘"row = self.table.rowCount()self.table.insertRow(row)# 填充表格self.table.setItem(row, 0, QTableWidgetItem(left_value))self.table.setItem(row, 1, QTableWidgetItem(right_value))self.table.setItem(row, 2, QTableWidgetItem(match))

导出结果到 Excel

def export_results(self):timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")file_path, _ = QFileDialog.getSaveFileName(self, "保存 Excel", f"对比结果_{timestamp}.xlsx", "Excel 文件 (*.xlsx)")if not file_path:return# 创建 Excel 文件并保存数据wb = openpyxl.Workbook()ws = wb.activews.append(["左侧数据", "右侧数据", "匹配状态", "内容对比"])for row in range(self.table.rowCount()):left_data = self.table.item(row, 0).text()right_data = self.table.item(row, 1).text()match_status = self.table.item(row, 2).text()compare_info = self.table.item(row, 3).text()ws.append([left_data, right_data, match_status, compare_info])if match_status == "✘":for col in range(1, 5):ws.cell(row=row+2, column=col).fill = red_fillwb.save(file_path)

3.效果展示:

在这里插入图片描述
在这里插入图片描述

4. 相关源码:

import sys
import pandas as pd
from PyQt5.QtWidgets import (QApplication, QWidget, QVBoxLayout, QHBoxLayout, QPushButton,QFileDialog, QTableWidget, QTableWidgetItem, QLabel, QComboBox, QMessageBox
)
from PyQt5.QtGui import QBrush, QColor
from datetime import datetime
import openpyxl
from openpyxl.styles import PatternFillclass ExcelComparator(QWidget):def __init__(self):super().__init__()self.initUI()
#def initUI(self):self.setWindowTitle("Excel 数据对比工具")self.setGeometry(100, 100, 900, 500)# 应用 QSS 美化界面self.setStyleSheet("""QWidget { background-color: #f4f4f4; }QPushButton { background-color: #0078D7; color: white; border-radius: 5px; padding: 8px; font-size: 14px;}QPushButton:hover { background-color: #005A9E; }QTableWidget { background-color: white; gridline-color: #CCC; }QLabel { font-size: 14px;  }""")layout = QVBoxLayout()# 文件选择区file_layout = QHBoxLayout()self.left_label = QLabel("左侧文件:")self.right_label = QLabel("右侧文件:")self.left_btn = QPushButton("打开")self.right_btn = QPushButton("打开")self.left_btn.clicked.connect(lambda: self.load_file("left"))self.right_btn.clicked.connect(lambda: self.load_file("right"))file_layout.addWidget(self.left_label)file_layout.addWidget(self.left_btn)file_layout.addWidget(self.right_label)file_layout.addWidget(self.right_btn)# Sheet 选择区sheet_layout = QHBoxLayout()self.left_sheet = QComboBox()self.right_sheet = QComboBox()self.left_sheet.currentIndexChanged.connect(lambda: self.load_sheet("left"))self.right_sheet.currentIndexChanged.connect(lambda: self.load_sheet("right"))sheet_layout.addWidget(QLabel("左侧 Sheet:"))sheet_layout.addWidget(self.left_sheet)sheet_layout.addWidget(QLabel("右侧 Sheet:"))sheet_layout.addWidget(self.right_sheet)# 对比列选择column_layout = QHBoxLayout()self.left_column = QComboBox()self.right_column = QComboBox()column_layout.addWidget(QLabel("左侧对比列:"))column_layout.addWidget(self.left_column)column_layout.addWidget(QLabel("右侧对比列:"))column_layout.addWidget(self.right_column)# 结果表格self.table = QTableWidget()self.table.setColumnCount(4)self.table.setHorizontalHeaderLabels(["左侧数据", "右侧数据", "匹配状态", "内容对比"])# 操作按钮button_layout = QHBoxLayout()self.compare_btn = QPushButton("开始对比")self.export_btn = QPushButton("导出结果")self.reset_btn = QPushButton("重置界面")self.exit_btn = QPushButton("退出程序")self.compare_btn.clicked.connect(self.compare_data)self.export_btn.clicked.connect(self.export_results)self.reset_btn.clicked.connect(self.reset_ui)self.exit_btn.clicked.connect(self.close)button_layout.addWidget(self.compare_btn)button_layout.addWidget(self.export_btn)button_layout.addWidget(self.reset_btn)button_layout.addWidget(self.exit_btn)# 布局组合layout.addLayout(file_layout)layout.addLayout(sheet_layout)layout.addLayout(column_layout)layout.addWidget(self.table)layout.addLayout(button_layout)self.setLayout(layout)def load_file(self, side):file_path, _ = QFileDialog.getOpenFileName(self, "选择 Excel 文件", "", "Excel 文件 (*.xlsx *.xls)")if not file_path:returnif side == "left":self.left_label.setText(f"左侧文件: {file_path}")self.left_file = file_pathself.left_sheet.clear()else:self.right_label.setText(f"右侧文件: {file_path}")self.right_file = file_pathself.right_sheet.clear()try:sheets = pd.ExcelFile(file_path).sheet_namesif side == "left":self.left_sheet.addItems(sheets)else:self.right_sheet.addItems(sheets)except Exception as e:QMessageBox.warning(self, "错误", f"无法读取 Excel 文件: {e}")def load_sheet(self, side):if side == "left":file, sheet_combo, column_combo = self.left_file, self.left_sheet, self.left_columnelse:file, sheet_combo, column_combo = self.right_file, self.right_sheet, self.right_columnif not file or sheet_combo.currentText() == "":returntry:df = pd.read_excel(file, sheet_name=sheet_combo.currentText())df.columns = df.columns.map(str)  # 确保列名是字符串column_combo.clear()column_combo.addItems(df.columns)except Exception as e:QMessageBox.warning(self, "错误", f"无法加载 Sheet 数据: {e}")def compare_data(self):left_col = self.left_column.currentText()right_col = self.right_column.currentText()if not left_col or not right_col:QMessageBox.warning(self, "错误", "请选择要对比的列!")returndf_left = pd.read_excel(self.left_file, sheet_name=self.left_sheet.currentText())df_right = pd.read_excel(self.right_file, sheet_name=self.right_sheet.currentText())df_left.columns = df_left.columns.map(str)df_right.columns = df_right.columns.map(str)self.table.setRowCount(0)for i in range(min(len(df_left), len(df_right))):left_value = str(df_left[left_col].iloc[i])right_value = str(df_right[right_col].iloc[i])match = "✔" if left_value == right_value else "✘"row = self.table.rowCount()self.table.insertRow(row)# 左侧数据列if not self.table.item(row, 0):self.table.setItem(row, 0, QTableWidgetItem(left_value))else:self.table.item(row, 0).setText(left_value)# 右侧数据列if not self.table.item(row, 1):self.table.setItem(row, 1, QTableWidgetItem(right_value))else:self.table.item(row, 1).setText(right_value)# 匹配状态列item_match = QTableWidgetItem(match)if not self.table.item(row, 2):self.table.setItem(row, 2, item_match)else:self.table.item(row, 2).setText(match)# 高亮不匹配的行if match == "✘":for col in range(4):  # 增加第四列的信息对比内容列表if not self.table.item(row, col):self.table.setItem(row, col, QTableWidgetItem())self.table.item(row, col).setBackground(QBrush(QColor(255, 150, 150)))# 对比内容显示differences = f"左侧: {left_value} | 右侧: {right_value}"if not self.table.item(row, 3):self.table.setItem(row, 3, QTableWidgetItem(differences))else:self.table.item(row, 3).setText(differences)def export_results(self):timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")file_path, _ = QFileDialog.getSaveFileName(self, "保存 Excel", f"对比结果_{timestamp}.xlsx", "Excel 文件 (*.xlsx)")if not file_path:returnwb = openpyxl.Workbook()ws = wb.activews.append(["左侧数据", "右侧数据", "匹配状态", "内容对比"])red_fill = PatternFill(start_color="FF9999", end_color="FF9999", fill_type="solid")for row in range(self.table.rowCount()):left_data = self.table.item(row, 0).text()right_data = self.table.item(row, 1).text()match_status = self.table.item(row, 2).text()compare_info = self.table.item(row, 3).text()ws.append([left_data, right_data, match_status, compare_info])if match_status == "✘":for col in range(1, 5):ws.cell(row=row+2, column=col).fill = red_fillwb.save(file_path)def reset_ui(self):self.left_sheet.clear()self.right_sheet.clear()self.left_column.clear()self.right_column.clear()self.table.setRowCount(0)if __name__ == "__main__":app = QApplication(sys.argv)window = ExcelComparator()window.show()sys.exit(app.exec_())

5.总结:

通过 PyQt5 和 pandas,我们快速实现了一个 Excel 数据对比工具,能够高效地处理两个 Excel 文件的内容对比,并自动高亮显示差异。此外,用户可以方便地导出对比结果,以便后续的查看和分析。对于需要频繁进行数据比对的工作人员而言,这款工具无疑能够大幅度提高工作效率,减少人工错误。

在未来的版本中,可以考虑以下几点扩展:

  • 多列对比:支持用户选择多个列进行对比。
  • 性能优化:对于大数据量的 Excel 文件,可以优化读取和比较的速度。
  • 自动化脚本:将此工具的功能封装为命令行工具,便于批量处理。

通过不断优化与扩展,我们能够将这款工具打造得更加完善,成为每位数据分析师和审计人员的得力助手。

以上就是本篇文章的完整内容。如果你有任何问题或建议,欢迎留言讨论。希望这篇文章能为你带来启发和帮助!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/39337.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

注册登录表单

html登录页面&#xff1a; <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>创建一个登录页面</t…

JAVA:Spring Boot @Conditional 注解详解及实践

1、简述 在 Spring Boot 中&#xff0c;Conditional 注解用于实现 条件化 Bean 装配&#xff0c;即根据特定的条件来决定是否加载某个 Bean。它是 Spring 框架中的一个扩展机制&#xff0c;常用于实现模块化、可配置的组件加载。 本文将详细介绍 Conditional 相关的注解&…

Java高频面试之集合-17

hello啊&#xff0c;各位观众姥爷们&#xff01;&#xff01;&#xff01;本baby今天来报道了&#xff01;哈哈哈哈哈嗝&#x1f436; 面试官&#xff1a;JDK 8 对 HashMap 主要做了哪些优化呢&#xff1f;为什么要这么做&#xff1f; JDK 8 对 HashMap 的主要优化及原因 JDK…

力扣DAY24 | 热100 | 回文链表

前言 简单 √ 是反转链表的衍生题&#xff0c;很快写完了。不过没考虑到恢复链表结构的问题。 题目 给你一个单链表的头节点 head &#xff0c;请你判断该链表是否为回文链表。如果是&#xff0c;返回 true &#xff1b;否则&#xff0c;返回 false 。 示例 1&#xff1a; 输…

Unity跨平台构建快速回顾

知识点来源&#xff1a;人间自有韬哥在&#xff0c;豆包 目录 一、发布应用程序1. 修改发布必备设置1.1 打开设置面板1.2 修改公司名、游戏项目名、版本号和默认图标1.3 修改 Package Name 和 Minimum API Level 2. 发布应用程序2.1 配置 Build Settings2.2 选择发布选项2.3 构…

手敲NLP相关神经网络,熟悉神经网络的结构与实现!

一、NNLM 二、word2vec 三、TextCNN 四、TextRNN 五、TextLSTM 六、Bi-LSTM 七、seq2seq 八、seq2seq&#xff08;attention&#xff09;

Spring MVC 拦截器使用

javaweb过滤器和springmvc拦截器&#xff1a; 拦截器的概念 拦截器使用 1/创建拦截器类&#xff0c;类中实现 handler执行前&#xff0c;执行后与渲染视图后的具体实现方法 public class GlobalExceptionHandler implements HandlerInterceptor {// if( ! preHandler()){re…

数据库分类、存储引擎、介绍、Mysql、SQL分类

DAY17.1 Java核心基础 数据库 关系型数据库&#xff08;传统数据库&#xff0c;安全可靠&#xff0c;数据量大&#xff09;&#xff1a;Mysql、Oracle、SQLServer 非关系型数据库nosql&#xff08;缓存数据库&#xff0c;高并发项目中&#xff0c;存储热点数据&#xff0c;短信…

Extend module 01:Keyboard

目录 一、Keyboard &#xff08;1&#xff09;资源介绍 &#x1f505;原理图 &#x1f505;扫描原理 &#xff08;2&#xff09;STM32CubeMX 软件配置 &#xff08;3&#xff09;代码编写 &#xff08;4&#xff09;实验现象 二、Keyboard接口函数封装 三、踩坑日记 &a…

【机器人】复现 GrainGrasp 精细指导的灵巧手抓取

GrainGrasp为每个手指提供细粒度的接触指导&#xff0c;为灵巧手生成精细的抓取策略。 通过单独调整每个手指的接触来实现更稳定的抓取&#xff0c;从而提供了更接近人类能力的抓取指导。 论文地址&#xff1a;GrainGrasp: Dexterous Grasp Generation with Fine-grained Con…

解锁 AWX+Ansible 自动化运维新体验:快速部署实战

Ansible 和 AWX 是自动化运维领域的强大工具组合。Ansible 是一个简单高效的 IT 自动化工具&#xff0c;而 AWX 则是 Ansible 的开源 Web 管理平台&#xff0c;提供图形化界面来管理 Ansible 任务。本指南将带你一步步在 Ubuntu 22.04 上安装 Ansible 和 AWX&#xff0c;使用 M…

Vulhub-jangow-01-1.0.1通关攻略

第0步&#xff1a; 打开靶机&#xff0c;按下shift&#xff0c;出现下图界面 在此页面按下e键&#xff0c;进入如下界面&#xff0c; 将ro 替换为 rw signie init/bin/bash 替换完毕后&#xff0c;按下Ctrl键X键&#xff0c;进入如下页面 ip a查看网卡信息 编辑配置文件网卡信…

默克生命科学 | ProClin™安全、高效防腐剂

ProClin™防腐剂是水溶性抗菌剂&#xff0c;是体外诊断(IVD)行业中最有效的抗菌剂之一&#xff0c;广泛应用于行业领先的诊断生产商的1,000多种FAD注册IVD试剂盒。低工作浓度下&#xff0c;ProClin™产品有效快速地抑制广谱微生物&#xff0c;有助于延长IVD试剂的保质期。 有别…

const应用

最近学校的花开了&#xff0c;选了一张三号楼窗前的白玉兰&#xff0c;(#^.^#) 1.修饰普通变量 当 const 用于修饰普通变量时&#xff0c;该变量的值在初始化之后就不能再改变。 #include <stdio.h>int main() {const int num 10;// num 20; // 错误&#xff0c;不…

FastStoneCapture下载安装教程(附安装包)专业截图工具

文章目录 前言FastStoneCapture下载FastStoneCapture安装步骤FastStoneCapture使用步骤 前言 在日常工作与学习里&#xff0c;高效截图工具至关重要。本教程将为你呈现FastStoneCapture下载安装教程&#xff0c;助你轻松拥有。 FastStoneCapture下载 FastStone Capture 是一款…

3. 轴指令(omron 机器自动化控制器)——>MC_ResetFollowingError

机器自动化控制器——第三章 轴指令 13 MC_ResetFollowingError变量▶输入变量▶输出变量▶输入输出变量 功能说明▶指令详情▶时序图▶重启动运动指令▶多重启运动指令▶异常 MC_ResetFollowingError 对指令当前位置和反馈当前位置的偏差进行复位。 指令名称FB/FUN图形表现S…

【HTML5游戏开发教程】零基础入门合成大西瓜游戏实战 | JS物理引擎+Canvas动画+完整源码详解

《从咖啡杯到财务自由&#xff1a;一个程序员的合成之旅——当代码遇上物理引擎的匠心之作》 &#x1f31f; 这是小游戏开发系列的第四篇送福利文章&#xff0c;感谢一路以来支持和关注这个项目的每一位朋友&#xff01; &#x1f4a1; 文章力求严谨&#xff0c;但难免有疏漏之…

举例说明自然语言处理(NLP)技术

当我们使用智能助手或社交媒体平台时&#xff0c;就会接触到自然语言处理&#xff08;NLP&#xff09;技术的应用。以下是一些常见的例子&#xff1a; 语音识别&#xff1a;当我们与智能助手如Siri、Alexa或Google Assistant交互时&#xff0c;我们说出语音命令&#xff0c;系统…

ResNet与注意力机制:深度学习中的强强联合

引言 在深度学习领域&#xff0c;卷积神经网络&#xff08;CNN&#xff09;一直是图像处理任务的主流架构。然而&#xff0c;随着网络深度的增加&#xff0c;梯度消失和梯度爆炸问题逐渐显现&#xff0c;限制了网络的性能。为了解决这一问题&#xff0c;ResNet&#xff08;残差…

【设计模式】组合模式

第11章 组合模式 11.1 一个基本的目录内容遍历范例 组合模式用于处理树形结构数据&#xff0c;如操作系统目录。以下是目录遍历的非组合模式实现&#xff1a; 文件类定义 class File { public:File(string name) : m_sname(name) {}void ShowName(string lvlstr) {cout <…