基于Python+PyQt5+Pandas编写的带图形界面的Excel合并工具

 更新时间:2026年01月12日 08:42:43   作者:weixin_46244623  
在日常办公或数据处理中,经常会遇到多个 Excel 文件需要合并的场景,手工复制不仅效率低,而且容易出错,本文将手把手教你使用 Python + PyQt5 + Pandas 编写一个带图形界面的 Excel 合并工具,需要的朋友可以参考下

引言

在日常办公或数据处理中,经常会遇到多个 Excel 文件需要合并的场景。手工复制不仅效率低,而且容易出错。

本文将手把手教你使用 Python + PyQt5 + Pandas 编写一个带图形界面的 Excel 合并工具,支持:

  • 选择文件夹
  • 自动读取多个 .xlsx 文件
  • 不同列自动对齐合并
  • 一键生成合并后的 Excel 文件
  • 自带程序图标(Base64 内嵌)

一、效果预览

功能说明:

  • 选择包含多个 .xlsx 文件的文件夹
  • 自动显示文件列表
  • 点击「合并 Excel 文件」
  • 在当前目录生成 合并.xlsx

二、环境准备

1、Python 版本

推荐:

Python 3.8+

2、安装依赖

pip install pyqt5 pandas openpyxl

说明:

库名用途
PyQt5GUI 图形界面
pandasExcel 数据处理
openpyxl读取 / 写入 xlsx

三、功能设计说明

1、合并逻辑说明

  • 逐个读取 Excel 文件
  • 自动收集 所有出现过的列
  • 不同文件中缺失的列自动补 NaN
  • 最终按列名对齐合并

示意:

文件
A.xlsx姓名、年龄
B.xlsx姓名、性别
合并结果姓名、年龄、性别

2、GUI 组件说明

组件功能
QLabel提示文本
QPushButton选择文件夹 / 合并
QFileDialog目录选择
QTableWidget文件列表
QMessageBox完成 / 错误提示

四、完整源码(可直接运行)

代码内嵌 Base64 图标,首次运行会自动生成 icon.png

import sys
import os
import pandas as pd
import base64
from PyQt5.QtWidgets import (
    QApplication, QWidget, QMessageBox, QPushButton,
    QFileDialog, QVBoxLayout, QLabel, QTableWidget, QTableWidgetItem
)
from PyQt5.QtGui import QIcon, QPixmap

Base64 图标处理

base64_icon = "data:image/png;base64,......(略)"
icon_data = base64_icon.split(',')[1]
icon_bytes = base64.b64decode(icon_data)

主窗口类

class ExcelMergerApp(QWidget):
    def __init__(self):
        super().__init__()
        self.initUI()

初始化 UI

def initUI(self):
    self.setWindowTitle('xlsx多个文件合并')
    self.setGeometry(100, 100, 800, 500)

    if os.path.exists('icon.png'):
        self.setWindowIcon(QIcon('icon.png'))
    else:
        pixmap = QPixmap()
        pixmap.loadFromData(icon_bytes)
        self.setWindowIcon(QIcon(pixmap))
        pixmap.save('icon.png', 'PNG')

    self.info_label = QLabel('选择包含要合并的Excel文件的文件夹:')
    self.select_folder_button = QPushButton('选择文件夹')
    self.merge_button = QPushButton('合并Excel文件')
    self.folder_label = QLabel('')

    self.file_table = QTableWidget()
    self.file_table.setColumnCount(1)
    self.file_table.setHorizontalHeaderLabels(['文件列表'])

    layout = QVBoxLayout()
    layout.addWidget(self.info_label)
    layout.addWidget(self.select_folder_button)
    layout.addWidget(self.folder_label)
    layout.addWidget(self.file_table)
    layout.addWidget(self.merge_button)

    self.setLayout(layout)

    self.select_folder_button.clicked.connect(self.get_folder)
    self.merge_button.clicked.connect(self.merge_excel_files)

选择文件夹 & 显示文件列表

def get_folder(self):
    folder = QFileDialog.getExistingDirectory(self, "选择包含Excel文件的文件夹")
    if folder:
        self.folder_path = folder
        self.folder_label.setText(f'选择的文件夹: {folder}')
        self.populate_file_table()
def populate_file_table(self):
    files = [f for f in os.listdir(self.folder_path) if f.endswith('.xlsx')]
    files.sort()
    self.file_table.setRowCount(len(files))
    for i, f in enumerate(files):
        self.file_table.setItem(i, 0, QTableWidgetItem(f))

Excel 合并核心逻辑

def merge_excel_files(self):
    if not hasattr(self, 'folder_path'):
        QMessageBox.critical(self, '错误', '请先选择文件夹')
        return

    merged_df = pd.DataFrame()

    for row in range(self.file_table.rowCount()):
        file_name = self.file_table.item(row, 0).text()
        file_path = os.path.join(self.folder_path, file_name)
        df = pd.read_excel(file_path)

        for col in df.columns:
            if col not in merged_df.columns:
                merged_df[col] = None

        merged_df = pd.concat([merged_df, df], ignore_index=True)

    output_path = os.path.join(self.folder_path, '合并.xlsx')
    merged_df.to_excel(output_path, index=False)

    QMessageBox.information(self, '完成', f'合并完成,文件保存到:\n{output_path}')

程序入口

if __name__ == '__main__':
    app = QApplication(sys.argv)
    window = ExcelMergerApp()
    window.show()
    sys.exit(app.exec_())

完整代码

import sys
import os
import pandas as pd
from PyQt5.QtWidgets import QApplication, QWidget,QMessageBox, QPushButton, QFileDialog, QVBoxLayout, QLabel, QTableWidget, QTableWidgetItem
from PyQt5.QtCore import Qt,QByteArray
from PyQt5.QtGui import QIcon, QPixmap
import base64
base64_icon = "data:image/png;base64,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"
icon_data = base64_icon.split(',')[1]
icon_bytes = base64.b64decode(icon_data)
class ExcelMergerApp(QWidget):
    def __init__(self):
        super().__init__()
        self.initUI()

    def initUI(self):
        self.setWindowTitle('xlsx多个文件合并')
        self.setGeometry(100, 100, 800, 500)
        if os.path.exists('icon.png'):
            icon = QIcon('icon.png')
            self.setWindowIcon(icon)
        else:
             # 将字节数据转换为 QPixmap
            pixmap = QPixmap()
            pixmap.loadFromData(icon_bytes)

            # 创建 QIcon 并将其设置为窗口图标
            icon = QIcon(pixmap)
            self.setWindowIcon(icon)
            pixmap.save('icon.png', 'PNG')
        

        self.info_label = QLabel('选择包含要合并的Excel文件的文件夹:')
        self.select_folder_button = QPushButton('选择文件夹')
        self.merge_button = QPushButton('合并Excel文件')

        self.folder_label = QLabel('')
        
        self.file_table = QTableWidget()
        self.file_table.setColumnCount(1)
        self.file_table.setHorizontalHeaderLabels(['文件列表'])

        layout = QVBoxLayout()
        layout.addWidget(self.info_label)
        layout.addWidget(self.select_folder_button)
        layout.addWidget(self.folder_label)
        layout.addWidget(self.file_table)
        layout.addWidget(self.merge_button)
        layout.addStretch()  
        self.setLayout(layout)

        self.select_folder_button.clicked.connect(self.get_folder)
        self.merge_button.clicked.connect(self.merge_excel_files)

    def get_folder(self):
        folder = QFileDialog.getExistingDirectory(self, "选择包含Excel文件的文件夹")
        if folder:
            self.folder_path = folder
            self.folder_label.setText(f'选择的文件夹: {folder}')
            self.populate_file_table()

    def populate_file_table(self):
        file_names = [file for file in os.listdir(self.folder_path) if file.endswith(".xlsx")]
        file_names.sort()  # Sort the file names
        self.file_table.setRowCount(len(file_names))
        for i, file_name in enumerate(file_names):
            item = QTableWidgetItem(file_name)
            self.file_table.setItem(i, 0, item)

    def merge_excel_files(self):
        if hasattr(self, 'folder_path'):
            # 添加您在上面的代码中执行的Excel文件合并操作
            unique_columns = pd.DataFrame()
            for row in range(self.file_table.rowCount()):
                file_name = self.file_table.item(row, 0).text()
                file_path = os.path.join(self.folder_path, file_name)
                df = pd.read_excel(file_path)
                file_columns = df.columns
                for column in file_columns:
                    if column not in unique_columns.columns:
                        unique_columns[column] = None
                unique_columns = pd.concat([unique_columns, df[file_columns]], ignore_index=True)

            # 保存合并后的数据到output.xlsx文件,包括列名
            output_file = "合并.xlsx"
            output_file_path = os.path.join(self.folder_path, output_file)
            unique_columns.to_excel(output_file_path, index=False)
            msg = QMessageBox()
            icon = QIcon("icon.png")
            msg.setWindowIcon(icon)
            msg.setIcon(QMessageBox.Information)
            msg.setText(f'合并完成,结果保存到 {output_file_path}')
            msg.setWindowTitle('合并完成')
            msg.exec_()
        else:
            msg = QMessageBox()
            icon = QIcon("icon.png")
            msg.setWindowIcon(icon)
            msg.setIcon(QMessageBox.Critical)
            msg.setText('请选择文件夹以合并Excel文件')
            msg.setWindowTitle('错误')
            msg.exec()

if __name__ == '__main__':
    app = QApplication(sys.argv)
    ex = ExcelMergerApp()
    ex.show()
    sys.exit(app.exec_())

到此这篇关于基于Python+PyQt5+Pandas编写的带图形界面的Excel合并工具的文章就介绍到这了,更多相关Python PyQt5 Excel合并工具内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • python批量爬取图片的方法详解

    python批量爬取图片的方法详解

    这篇文章给大家介绍了如何使用python批量爬取图片,文中通过代码示例给大家介绍的非常详细,对大家的学习或工作有一定的帮助,需要的朋友可以参考下
    2023-12-12
  • Python即时网络爬虫项目启动说明详解

    Python即时网络爬虫项目启动说明详解

    这篇文章主要为大家详细介绍了Python即时网络爬虫项目启动说明,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-02-02
  • python+selenium实现12306模拟登录的步骤

    python+selenium实现12306模拟登录的步骤

    这篇文章主要介绍了python+selenium实现12306模拟登录的步骤,帮助大家更好的理解和使用python,感兴趣的朋友可以了解下
    2021-01-01
  • Python命令行参数解析包argparse的使用详解

    Python命令行参数解析包argparse的使用详解

    argparse 是 python 自带的命令行参数解析包,可以用来方便的服务命令行参数。本文将通过示例和大家详细讲讲argparse的使用,需要的可以参考一下
    2022-09-09
  • jupyter实现重新加载模块

    jupyter实现重新加载模块

    这篇文章主要介绍了jupyter实现重新加载模块,具有很好的价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-04-04
  • Python使用FTP上传文件的实现示例

    Python使用FTP上传文件的实现示例

    本文主要介绍了Python使用FTP上传文件的实现示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-03-03
  • Python urlopen()函数 示例分享

    Python urlopen()函数 示例分享

    urlopen(url, data=None, proxies=None) 即创建一个表示远程url的类文件对象,然后像本地文件一样操作这个类文件对象来获取远程数据。参数url表示远程数据的路径,一般是网址;参数data表示以post方式提交到url的数据;参数proxies用于设置代理。
    2014-06-06
  • Python简单生成随机姓名的方法示例

    Python简单生成随机姓名的方法示例

    这篇文章主要介绍了Python简单生成随机姓名的方法,结合实例形式分析了Python基于random模块生成随机字符串组合的相关操作技巧,需要的朋友可以参考下
    2017-12-12
  • 解决Python selenium get页面很慢时的问题

    解决Python selenium get页面很慢时的问题

    今天小编就为大家分享一篇解决Python selenium get页面很慢时的问题,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2019-01-01
  • windows10 pycharm下安装pyltp库和加载模型实现语义角色标注的示例代码

    windows10 pycharm下安装pyltp库和加载模型实现语义角色标注的示例代码

    这篇文章主要介绍了windows10 pycharm下安装pyltp库和加载模型实现语义角色标注,本文通过图文实例相结合给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-05-05

最新评论