最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

基于Python+PyQt5+Pandas編寫的帶圖形界面的Excel合并工具

 更新時間:2026年01月12日 08:42:43   作者:weixin_46244623  
在日常辦公或數(shù)據(jù)處理中,經(jīng)常會遇到多個 Excel 文件需要合并的場景,手工復(fù)制不僅效率低,而且容易出錯,本文將手把手教你使用 Python + PyQt5 + Pandas 編寫一個帶圖形界面的 Excel 合并工具,需要的朋友可以參考下

引言

在日常辦公或數(shù)據(jù)處理中,經(jīng)常會遇到多個 Excel 文件需要合并的場景。手工復(fù)制不僅效率低,而且容易出錯。

本文將手把手教你使用 Python + PyQt5 + Pandas 編寫一個帶圖形界面的 Excel 合并工具,支持:

  • 選擇文件夾
  • 自動讀取多個 .xlsx 文件
  • 不同列自動對齊合并
  • 一鍵生成合并后的 Excel 文件
  • 自帶程序圖標(biāo)(Base64 內(nèi)嵌)

一、效果預(yù)覽

功能說明:

  • 選擇包含多個 .xlsx 文件的文件夾
  • 自動顯示文件列表
  • 點(diǎn)擊「合并 Excel 文件」
  • 在當(dāng)前目錄生成 合并.xlsx

二、環(huán)境準(zhǔn)備

1、Python 版本

推薦:

Python 3.8+

2、安裝依賴

pip install pyqt5 pandas openpyxl

說明:

庫名用途
PyQt5GUI 圖形界面
pandasExcel 數(shù)據(jù)處理
openpyxl讀取 / 寫入 xlsx

三、功能設(shè)計說明

1、合并邏輯說明

  • 逐個讀取 Excel 文件
  • 自動收集 所有出現(xiàn)過的列
  • 不同文件中缺失的列自動補(bǔ) NaN
  • 最終按列名對齊合并

示意:

文件
A.xlsx姓名、年齡
B.xlsx姓名、性別
合并結(jié)果姓名、年齡、性別

2、GUI 組件說明

組件功能
QLabel提示文本
QPushButton選擇文件夾 / 合并
QFileDialog目錄選擇
QTableWidget文件列表
QMessageBox完成 / 錯誤提示

四、完整源碼(可直接運(yùn)行)

代碼內(nèi)嵌 Base64 圖標(biāo),首次運(yùn)行會自動生成 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 圖標(biāo)處理

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:
             # 將字節(jié)數(shù)據(jù)轉(zhuǎn)換為 QPixmap
            pixmap = QPixmap()
            pixmap.loadFromData(icon_bytes)

            # 創(chuàng)建 QIcon 并將其設(shè)置為窗口圖標(biāo)
            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'):
            # 添加您在上面的代碼中執(zhí)行的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)

            # 保存合并后的數(shù)據(jù)到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'合并完成,結(jié)果保存到 {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_())

到此這篇關(guān)于基于Python+PyQt5+Pandas編寫的帶圖形界面的Excel合并工具的文章就介紹到這了,更多相關(guān)Python PyQt5 Excel合并工具內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Python返回真假值(True or False)小技巧

    Python返回真假值(True or False)小技巧

    這篇文章主要介紹了Python返回真假值(True or False)小技巧,本文探討的是最簡潔的條件判斷語句寫法,本文給出了兩種簡潔寫法,需要的朋友可以參考下
    2015-04-04
  • Python使用XPath進(jìn)行正則表達(dá)式匹配的實戰(zhàn)指南

    Python使用XPath進(jìn)行正則表達(dá)式匹配的實戰(zhàn)指南

    在Web自動化測試和數(shù)據(jù)抓取中,我們經(jīng)常遇到動態(tài)生成的HTML屬性,傳統(tǒng)XPath定位方式容易因這些變化而失效,下面我們就來看看Python中如何運(yùn)用XPath正則匹配吧
    2026-04-04
  • python 限制函數(shù)調(diào)用次數(shù)的實例講解

    python 限制函數(shù)調(diào)用次數(shù)的實例講解

    下面小編就為大家分享一篇python 限制函數(shù)調(diào)用次數(shù)的實例講解,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2018-04-04
  • Python對列表進(jìn)行排序的5種實現(xiàn)方式

    Python對列表進(jìn)行排序的5種實現(xiàn)方式

    這篇文章介紹了五種在Python中進(jìn)行排序的方法,包括sort()方法、sorted()函數(shù)、lambda表達(dá)式作為key參數(shù)進(jìn)行排序、operator模塊進(jìn)行排序以及numpy模塊進(jìn)行排序,每種方法都有其適用的場景和優(yōu)勢,可以根據(jù)具體需要選擇最合適的方法
    2025-12-12
  • python繪制散點(diǎn)圖詳細(xì)步驟(從0到1必會)

    python繪制散點(diǎn)圖詳細(xì)步驟(從0到1必會)

    這篇文章主要介紹了如何使用Python繪制散點(diǎn)圖,包括導(dǎo)入包、準(zhǔn)備數(shù)據(jù)、繪制圖像、修飾圖像(添加標(biāo)題、坐標(biāo)軸標(biāo)簽、顏色圖例)以及整合所有代碼,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2024-12-12
  • 經(jīng)驗豐富程序員才知道的15種高級Python小技巧(收藏)

    經(jīng)驗豐富程序員才知道的15種高級Python小技巧(收藏)

    本文將介紹15個簡潔的Python技巧,向著簡潔更高效,學(xué)習(xí)易懂出發(fā),具說只有經(jīng)驗豐富程序員才知道的15種高級Python小技巧,喜歡的朋友快來看看吧
    2021-10-10
  • Python中的pynput使用方法

    Python中的pynput使用方法

    pynput是一個Python 庫,用于監(jiān)控和控制輸入設(shè)備,如鍵盤和鼠標(biāo),本文通過一個簡單的示例,展示如何使用pynput控制鼠標(biāo),本文結(jié)合實例代碼給大家介紹的非常詳細(xì),感興趣的朋友一起看看吧
    2026-02-02
  • Python中requests、aiohttp、httpx性能比拼

    Python中requests、aiohttp、httpx性能比拼

    本文主要介紹了Python中requests、aiohttp、httpx性能比拼,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-06-06
  • Python 高級專用類方法的實例詳解

    Python 高級專用類方法的實例詳解

    這篇文章主要介紹了Python 高級專用類方法的實例詳解的相關(guān)資料,希望通過本文大家能夠掌握這部分內(nèi)容,需要的朋友可以參考下
    2017-09-09
  • Python 利用argparse模塊實現(xiàn)腳本命令行參數(shù)解析

    Python 利用argparse模塊實現(xiàn)腳本命令行參數(shù)解析

    這篇文章主要介紹了Python 利用argparse模塊實現(xiàn)腳本命令行參數(shù)解析,本文通過實例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-12-12

最新評論

社旗县| 渝北区| 岑巩县| 鲁甸县| 德惠市| 葵青区| 承德县| 元阳县| 阳山县| 临颍县| 林甸县| 普兰店市| 岳普湖县| 凤庆县| 盐山县| 铜陵市| 合水县| 凌云县| 金堂县| 布尔津县| 介休市| 莆田市| 子长县| 大理市| 同心县| 灵宝市| 寿光市| 永川市| 新兴县| 贵港市| 南漳县| 明光市| 阜南县| 瓦房店市| 麻栗坡县| 西安市| 渭源县| 旬邑县| 保康县| 河北区| 武陟县|