云计算、AI、云原生、大数据等一站式技术学习平台

网站首页 > 教程文章 正文

制作pyQt5设计一个Excel合并工具以及功能实现编写

jxf315 2024-12-17 14:08:31 教程文章 42 ℃

UI设计(designer)


将.ui文件转为.py文件

pyuic5 -o xxxxx.py xxxxx.ui

添加代码

if __name__ == "__main__":
    app = QtWidgets.QApplication(sys.argv)
    Form = QtWidgets.QWidget()
    ui = Ui_Form()
    ui.setupUi(Form)
    Form.show()
    sys.exit(app.exec_())

功能实现(非多线程)

读取文件

    def open_file(self):
        # getOpenFileName(parent: QWidget = None, caption: str = '', directory: str = '', filter: str = '', initialFilter: str = '', options: Union[QFileDialog.Options, QFileDialog.Option] = 0)
        fileName, filetype=QFileDialog.getOpenFileName(caption='选择Excel文件',directory='./',filter='*.xlsx')
        self.textBrowser.append('{} 选择的文件为:{}'.format(time.strftime('%Y-%m-%d %H:%M:%S'),fileName))# 追加文本
        try:
            skiprows=int(self.lineEdit_skiprows.text())
            wbook=load_workbook(fileName) #打开工作簿
            wsheets=wbook.get_sheet_names() #获取工作表
            dfs=pd.read_excel(fileName,sheet_name=wsheets,skiprows=skiprows)
            self.dfs = dfs
            self.textBrowser.append('{} 已成功读取文件:{}'.format(time.strftime('%Y-%m-%d %H:%M:%S'),fileName))# 追加文本
        except BaseException as e:
            self.textBrowser.append('{} 文件{}读取失败,请核实后重新选择!\n{}'.format(time.strftime('%Y-%m-%d %H:%M:%S'),fileName,e))
       

合并文件

    def contrast_title(self):
        '''对比'''
        try:
            dfs=self.dfs
        except BaseException as e:
            self.textBrowser.append('{} 请先读取文件!'.format(time.strftime('%Y-%m-%d %H:%M:%S'),e))# 追加文本
            return None
        try:
            i=0
            for sheetname in dfs.keys():
                i+=1
                tmpdf=dfs[sheetname]
                c0=list(tmpdf.columns)
                tmpdfc0=pd.DataFrame([[c0[i],'√'] for i in range(len(c0))],columns=['columns',sheetname])
                if i==1:
                    df=tmpdfc0
                else:
                    df = pd.merge(df,tmpdfc0,how='outer',on='columns')
            self.df=df
            self.textBrowser.append('{} 工作表标题对比完成!'.format(time.strftime('%Y-%m-%d %H:%M:%S')))# 追加文本
        except BaseException as e:
            self.textBrowser.append('{}'.format(e))# 追加文本
            self.textBrowser.append('{} 工作表标题对比失败!'.format(time.strftime('%Y-%m-%d %H:%M:%S')))# 追加文本
        self.progressBar.setProperty("value", 50)

标题对比

    def contrast_title(self):
        '''对比'''
        try:
            dfs=self.dfs
        except BaseException as e:
            self.textBrowser.append('{} 请先读取文件!'.format(time.strftime('%Y-%m-%d %H:%M:%S'),e))# 追加文本
            return None
        try:
            i=0
            for sheetname in dfs.keys():
                i+=1
                tmpdf=dfs[sheetname]
                c0=list(tmpdf.columns)
                tmpdfc0=pd.DataFrame([[c0[i],'√'] for i in range(len(c0))],columns=['columns',sheetname])
                if i==1:
                    df=tmpdfc0
                else:
                    df = pd.merge(df,tmpdfc0,how='outer',on='columns')
            self.df=df
            self.textBrowser.append('{} 工作表标题对比完成!'.format(time.strftime('%Y-%m-%d %H:%M:%S')))# 追加文本
        except BaseException as e:
            self.textBrowser.append('{}'.format(e))# 追加文本
            self.textBrowser.append('{} 工作表标题对比失败!'.format(time.strftime('%Y-%m-%d %H:%M:%S')))# 追加文本
        self.progressBar.setProperty("value", 50)

结果保存

    def save_file(self):
        '''保存'''
        try:
            df=self.df
        except BaseException as e:
            self.textBrowser.append('{} 请先对文件内容进行合并或者对比!'.format(time.strftime('%Y-%m-%d %H:%M:%S'),e))# 追加文本
            return None
        
        fileName, filetype = QFileDialog.getSaveFileName(caption='保存文件',directory='./',filter='*.xlsx')
        self.textBrowser.append('{} 文件将保存至:{}'.format(time.strftime('%Y-%m-%d %H:%M:%S'),fileName))# 追加文本
        try:
            if self.checkBox_index.isChecked():
                df.to_excel(fileName,index=True)
            else:
                df.to_excel(fileName,index=False)
            self.textBrowser.append('{} 文件已保存至:{}'.format(time.strftime('%Y-%m-%d %H:%M:%S'),fileName))# 追加文本
        except BaseException as e:
            self.textBrowser.append('{} 文件{}保存失败!'.format(time.strftime('%Y-%m-%d %H:%M:%S'),fileName))# 追加文本
        self.progressBar.setProperty("value", 100)

参数实现

    def change_ignore(self):
        if self.checkBox_ignore.isChecked():
            self.textBrowser.append('{now} 重构索引列:是!'.format(now=time.strftime('%Y-%m-%d %H:%M:%S')))
        else:
            self.textBrowser.append('{now} 重构索引列:否!'.format(now=time.strftime('%Y-%m-%d %H:%M:%S')))
            
    def change_index(self):
        if self.checkBox_index.isChecked():
            self.textBrowser.append('{now} 写入索引列:是!'.format(now=time.strftime('%Y-%m-%d %H:%M:%S')))
        else:
            self.textBrowser.append('{now} 写入索引列:否!'.format(now=time.strftime('%Y-%m-%d %H:%M:%S')))

全代码

# -*- coding: utf-8 -*-

# Form implementation generated from reading ui file '工作表合并.ui'
#
# Created by: PyQt5 UI code generator 5.12.3
#
# WARNING! All changes made in this file will be lost!


from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtWidgets import QFileDialog
import pandas as pd
import sys
from openpyxl import load_workbook #导入Excel工作表操作模块
import time


class Ui_Form(object):
    def setupUi(self, Form):
        Form.setObjectName("Form")
        Form.resize(376, 276)
        self.gridLayout_2 = QtWidgets.QGridLayout(Form)
        self.gridLayout_2.setObjectName("gridLayout_2")
        self.groupBox_operate = QtWidgets.QGroupBox(Form)
        self.groupBox_operate.setObjectName("groupBox_operate")
        self.gridLayout_4 = QtWidgets.QGridLayout(self.groupBox_operate)
        self.gridLayout_4.setObjectName("gridLayout_4")
        self.pushButton_openfile = QtWidgets.QPushButton(self.groupBox_operate)
        self.pushButton_openfile.setObjectName("pushButton_openfile")
        self.gridLayout_4.addWidget(self.pushButton_openfile, 0, 0, 1, 1)
        self.pushButton_merge = QtWidgets.QPushButton(self.groupBox_operate)
        self.pushButton_merge.setObjectName("pushButton_merge")
        self.gridLayout_4.addWidget(self.pushButton_merge, 0, 1, 1, 1)
        self.pushButton_contrast = QtWidgets.QPushButton(self.groupBox_operate)
        self.pushButton_contrast.setObjectName("pushButton_contrast")
        self.gridLayout_4.addWidget(self.pushButton_contrast, 1, 0, 1, 1)
        self.pushButton_savefile = QtWidgets.QPushButton(self.groupBox_operate)
        self.pushButton_savefile.setObjectName("pushButton_savefile")
        self.gridLayout_4.addWidget(self.pushButton_savefile, 1, 1, 1, 1)
        self.progressBar = QtWidgets.QProgressBar(self.groupBox_operate)
        self.progressBar.setProperty("value", 0)
        self.progressBar.setObjectName("progressBar")
        self.gridLayout_4.addWidget(self.progressBar, 2, 0, 1, 2)
        self.gridLayout_2.addWidget(self.groupBox_operate, 0, 1, 1, 1)
        self.gridLayout = QtWidgets.QGridLayout()
        self.gridLayout.setObjectName("gridLayout")
        self.groupBox_set = QtWidgets.QGroupBox(Form)
        self.groupBox_set.setObjectName("groupBox_set")
        self.gridLayout_3 = QtWidgets.QGridLayout(self.groupBox_set)
        self.gridLayout_3.setObjectName("gridLayout_3")
        self.lineEdit_skiprows = QtWidgets.QLineEdit(self.groupBox_set)
        self.lineEdit_skiprows.setObjectName("lineEdit_skiprows")
        self.gridLayout_3.addWidget(self.lineEdit_skiprows, 0, 1, 1, 2)
        self.lineEdit_dropindex = QtWidgets.QLineEdit(self.groupBox_set)
        self.lineEdit_dropindex.setObjectName("lineEdit_dropindex")
        self.gridLayout_3.addWidget(self.lineEdit_dropindex, 1, 1, 1, 2)
        self.checkBox_ignore = QtWidgets.QCheckBox(self.groupBox_set)
        self.checkBox_ignore.setObjectName("checkBox_ignore")
        self.gridLayout_3.addWidget(self.checkBox_ignore, 2, 0, 1, 2)
        self.checkBox_index = QtWidgets.QCheckBox(self.groupBox_set)
        self.checkBox_index.setObjectName("checkBox_index")
        self.gridLayout_3.addWidget(self.checkBox_index, 2, 2, 1, 1)
        self.label_skiprows = QtWidgets.QLabel(self.groupBox_set)
        self.label_skiprows.setObjectName("label_skiprows")
        self.gridLayout_3.addWidget(self.label_skiprows, 0, 0, 1, 1)
        self.label_dropindex = QtWidgets.QLabel(self.groupBox_set)
        self.label_dropindex.setObjectName("label_dropindex")
        self.gridLayout_3.addWidget(self.label_dropindex, 1, 0, 1, 1)
        self.gridLayout.addWidget(self.groupBox_set, 0, 0, 1, 1)
        self.gridLayout_2.addLayout(self.gridLayout, 0, 0, 1, 1)
        self.groupBox_message = QtWidgets.QGroupBox(Form)
        self.groupBox_message.setObjectName("groupBox_message")
        self.gridLayout_5 = QtWidgets.QGridLayout(self.groupBox_message)
        self.gridLayout_5.setObjectName("gridLayout_5")
        self.textBrowser = QtWidgets.QTextBrowser(self.groupBox_message)
        self.textBrowser.setObjectName("textBrowser")
        self.gridLayout_5.addWidget(self.textBrowser, 0, 0, 1, 1)
        self.gridLayout_2.addWidget(self.groupBox_message, 1, 0, 1, 2)

        self.retranslateUi(Form)
        # 槽
        self.pushButton_openfile.clicked.connect(self.open_file)
        self.pushButton_merge.clicked.connect(self.concat_file)
        self.pushButton_contrast.clicked.connect(self.contrast_title)
        self.pushButton_savefile.clicked.connect(self.save_file)
        
        self.checkBox_ignore.stateChanged.connect(self.change_ignore) # 变更时调用函数
        self.checkBox_index.stateChanged.connect(self.change_index) # 变更时调用函数
        
        QtCore.QMetaObject.connectSlotsByName(Form)
        

    def retranslateUi(self, Form):
        _translate = QtCore.QCoreApplication.translate
        Form.setWindowTitle(_translate("Form", "Excel工作表合并"))
        self.groupBox_operate.setTitle(_translate("Form", "操作"))
        self.pushButton_openfile.setText(_translate("Form", "选择文件"))
        self.pushButton_merge.setText(_translate("Form", "合并文件"))
        self.pushButton_contrast.setText(_translate("Form", "标题对比"))
        self.pushButton_savefile.setText(_translate("Form", "保存文件"))
        self.groupBox_set.setTitle(_translate("Form", "设置"))
        self.checkBox_ignore.setText(_translate("Form", "重塑索引"))
        self.checkBox_index.setText(_translate("Form", "写入索引"))
        self.label_skiprows.setText(_translate("Form", "跳过行"))
        self.label_dropindex.setText(_translate("Form", "删除行"))
        self.groupBox_message.setTitle(_translate("Form", "消息"))
        
        self.lineEdit_skiprows.setText(_translate("Form", "0"))
        self.lineEdit_dropindex.setText(_translate("Form", "0"))
        self.checkBox_ignore.setChecked(True)
        


    def change_ignore(self):
        if self.checkBox_ignore.isChecked():
            self.textBrowser.append('{now} 重构索引列:是!'.format(now=time.strftime('%Y-%m-%d %H:%M:%S')))
        else:
            self.textBrowser.append('{now} 重构索引列:否!'.format(now=time.strftime('%Y-%m-%d %H:%M:%S')))
            
    def change_index(self):
        if self.checkBox_index.isChecked():
            self.textBrowser.append('{now} 写入索引列:是!'.format(now=time.strftime('%Y-%m-%d %H:%M:%S')))
        else:
            self.textBrowser.append('{now} 写入索引列:否!'.format(now=time.strftime('%Y-%m-%d %H:%M:%S')))
            
    
    def open_file(self):
        # getOpenFileName(parent: QWidget = None, caption: str = '', directory: str = '', filter: str = '', initialFilter: str = '', options: Union[QFileDialog.Options, QFileDialog.Option] = 0)
        fileName, filetype=QFileDialog.getOpenFileName(caption='选择Excel文件',directory='./',filter='*.xlsx')
        self.textBrowser.append('{} 选择的文件为:{}'.format(time.strftime('%Y-%m-%d %H:%M:%S'),fileName))# 追加文本
        try:
            skiprows=int(self.lineEdit_skiprows.text())
            wbook=load_workbook(fileName) #打开工作簿
            wsheets=wbook.get_sheet_names() #获取工作表
            dfs=pd.read_excel(fileName,sheet_name=wsheets,skiprows=skiprows)
            self.dfs = dfs
            self.textBrowser.append('{} 已成功读取文件:{}'.format(time.strftime('%Y-%m-%d %H:%M:%S'),fileName))# 追加文本
        except BaseException as e:
            self.textBrowser.append('{} 文件{}读取失败,请核实后重新选择!\n{}'.format(time.strftime('%Y-%m-%d %H:%M:%S'),fileName,e))
        

        

    def concat_file(self):
        '''合并'''
        df=pd.DataFrame()
        try:
            dfs=self.dfs
        except BaseException as e:
            self.textBrowser.append('{} 请先读取文件!'.format(time.strftime('%Y-%m-%d %H:%M:%S'),e))# 追加文本
            return None
        for sheetname in dfs.keys():
            self.textBrowser.append('{} 正在合并{}工作表……'.format(time.strftime('%Y-%m-%d %H:%M:%S'),sheetname))# 追加文本
            tmp=dfs[sheetname]
            tmpdf=tmp.copy(deep=True)
            try:
                drop_list=[int(i) for i in self.lineEdit_dropindex.text().split(',')]
                tmpdf.drop(labels=None,axis=0, index=drop_list, columns=None, inplace=True) # 删除一行
            except BaseException as e:
                self.textBrowser.append('{} 删除行解析异常,不做删除!'.format(e))# 追加文本
                drop_list=None
            tmpdf['SheetName']=sheetname
            try:
                if self.checkBox_ignore.isChecked():
                    df=pd.concat([df,tmpdf],ignore_index=True,axis=0)
                else:
                    df=pd.concat([df,tmpdf],ignore_index=False,axis=0)
            except BaseException as e:
                self.textBrowser.append('{}'.format(e))# 追加文本
                self.textBrowser.append('{} 合并{}工作表异常!'.format(time.strftime('%Y-%m-%d %H:%M:%S'),sheetname))# 追加文本
            
        self.df=df
        self.progressBar.setProperty("value", 80)
    
    def contrast_title(self):
        '''对比'''
        try:
            dfs=self.dfs
        except BaseException as e:
            self.textBrowser.append('{} 请先读取文件!'.format(time.strftime('%Y-%m-%d %H:%M:%S'),e))# 追加文本
            return None
        try:
            i=0
            for sheetname in dfs.keys():
                i+=1
                tmpdf=dfs[sheetname]
                c0=list(tmpdf.columns)
                tmpdfc0=pd.DataFrame([[c0[i],'√'] for i in range(len(c0))],columns=['columns',sheetname])
                if i==1:
                    df=tmpdfc0
                else:
                    df = pd.merge(df,tmpdfc0,how='outer',on='columns')
            self.df=df
            self.textBrowser.append('{} 工作表标题对比完成!'.format(time.strftime('%Y-%m-%d %H:%M:%S')))# 追加文本
        except BaseException as e:
            self.textBrowser.append('{}'.format(e))# 追加文本
            self.textBrowser.append('{} 工作表标题对比失败!'.format(time.strftime('%Y-%m-%d %H:%M:%S')))# 追加文本
        self.progressBar.setProperty("value", 50)
        
    def save_file(self):
        '''保存'''
        try:
            df=self.df
        except BaseException as e:
            self.textBrowser.append('{} 请先对文件内容进行合并或者对比!'.format(time.strftime('%Y-%m-%d %H:%M:%S'),e))# 追加文本
            return None
        
        fileName, filetype = QFileDialog.getSaveFileName(caption='保存文件',directory='./',filter='*.xlsx')
        self.textBrowser.append('{} 文件将保存至:{}'.format(time.strftime('%Y-%m-%d %H:%M:%S'),fileName))# 追加文本
        try:
            if self.checkBox_index.isChecked():
                df.to_excel(fileName,index=True)
            else:
                df.to_excel(fileName,index=False)
            self.textBrowser.append('{} 文件已保存至:{}'.format(time.strftime('%Y-%m-%d %H:%M:%S'),fileName))# 追加文本
        except BaseException as e:
            self.textBrowser.append('{} 文件{}保存失败!'.format(time.strftime('%Y-%m-%d %H:%M:%S'),fileName))# 追加文本
        self.progressBar.setProperty("value", 100)


if __name__ == "__main__":
    app = QtWidgets.QApplication(sys.argv)
    Form = QtWidgets.QWidget()
    ui = Ui_Form()
    ui.setupUi(Form)
    Form.show()
    sys.exit(app.exec_())

缺陷由于不是多线程,因此功能时间会导致界面假死

功能实现(多线程)

文件读取改造

class Thread_Openfile(QThread):
    _signal=pyqtSignal()
    message_signal=pyqtSignal(str)
    data_signal=pyqtSignal(dict)
    propert_signal=pyqtSignal(int)
    def __init__(self,fileName,skiprows):
        super().__init__()
        self.fileName=fileName
        self.skiprows=skiprows
        
        
    def run(self):
        self.message_signal.emit('正在读取文件,请等待!')
        dfs=pd.DataFrame()
        self.propert_signal.emit(2)
        try:
            wbook=load_workbook(self.fileName) #打开工作簿
            wsheets=wbook.get_sheet_names() #获取工作表
            self.propert_signal.emit(10)
            dfs=pd.read_excel(self.fileName,sheet_name=wsheets,skiprows=self.skiprows)
            message='已成功读取文件:{}'.format(self.fileName)
            
            self.data_signal.emit(dfs)
            
            self.message_signal.emit(message)
            self.propert_signal.emit(20)
        except BaseException as e:
            message=str(e)
            self.message_signal.emit(message)
            self.propert_signal.emit(0)
            
        finally:
            self._signal.emit()

文件合并

class Thread_Concatfile(QThread):
    _signal=pyqtSignal()
    message_signal=pyqtSignal(str)
    data_signal=pyqtSignal(dict)
    propert_signal=pyqtSignal(int)
    
    
    def __init__(self,dfs,isChecked,lineEdit_dropindex):
        super().__init__()
        self.dfs=dfs
        self.isChecked=isChecked
        self.lineEdit_dropindex=lineEdit_dropindex
        
        
    def run(self):
        dfs=self.dfs
        df=pd.DataFrame()
        long=len(dfs.keys())
        for sheetname in dfs.keys():
            message='正在合并{}工作表……'.format(sheetname)
            self.message_signal.emit(message)
            tmp=dfs[sheetname]
            tmpdf=tmp.copy(deep=True)
            try:
                drop_list=[int(i) for i in self.lineEdit_dropindex.split(',')]
                tmpdf.drop(labels=None,axis=0, index=drop_list, columns=None, inplace=True) # 删除一行
            except BaseException as e:
                message='{}\n表:{} 删除行解析异常,不做删除!'.format(e,sheetname)
                self.message_signal.emit(message)
                drop_list=None
            tmpdf['SheetName']=sheetname
            try:
                if self.isChecked:
                    df=pd.concat([df,tmpdf],ignore_index=True,axis=0)
                else:
                    df=pd.concat([df,tmpdf],ignore_index=False,axis=0)
            except BaseException as e:
                message='合并{}工作表异常!'.format(sheetname)
                self.message_signal.emit(message)
                
            finally:
                self.propert_signal.emit(20+60/long)
                
                
        self._signal.emit()
        self.data_signal.emit({'df':df})
        self.propert_signal.emit(80)

文件标题对比


class Thread_Contrasttitle(QThread):
    _signal=pyqtSignal()
    message_signal=pyqtSignal(str)
    data_signal=pyqtSignal(dict)
    propert_signal=pyqtSignal(int)
    
    def __init__(self,dfs):
        super().__init__()
        self.dfs=dfs
        
    def run(self):
        dfs=self.dfs
        try:
            i=0
            long=len(dfs.keys())
            for sheetname in dfs.keys():
                i+=1
                tmpdf=dfs[sheetname]
                c0=list(tmpdf.columns)
                tmpdfc0=pd.DataFrame([[c0[i],'√'] for i in range(len(c0))],columns=['columns',sheetname])
                self.propert_signal.emit(20+30/long)
                if i==1:
                    df=tmpdfc0
                else:
                    df = pd.merge(df,tmpdfc0,how='outer',on='columns')
            self.df=df
    
            message='工作表标题对比完成!'
            self.message_signal.emit(message)
            
            
        except BaseException as e:
            message='{}\n工作表对比失败!'.format(e)
            self.message_signal.emit(message)
        finally:
            
                
            self._signal.emit()
            self.data_signal.emit({'df':df})
            self.propert_signal.emit(50)

文件保存

class Thread_Savefile(QThread):
    _signal=pyqtSignal()
    message_signal=pyqtSignal(str)
    propert_signal=pyqtSignal(int)
    def __init__(self,df,isChecked,fileName):
        super().__init__()
        self.df=df
        self.isChecked=isChecked
        self.fileName=fileName
        
    def run(self):
        self._signal.emit()  
        df=self.df
        try:
            if self.isChecked:
                df.to_excel(self.fileName,index=True)
            else:
                df.to_excel(self.fileName,index=False)
            message='文件已保存至:{}'.format(self.fileName)
            self.message_signal.emit(message)
            
        except BaseException as e:
            message='{}\n文件{}保存失败!'.format(e,self.fileName)
        finally:    
            self.propert_signal.emit(100)

改造后的全代码

# -*- coding: utf-8 -*-

# Form implementation generated from reading ui file '工作表合并.ui'
#
# Created by: PyQt5 UI code generator 5.12.3
#
# WARNING! All changes made in this file will be lost!


from PyQt5 import QtCore, QtWidgets # QtGui
from PyQt5.QtWidgets import QFileDialog
from PyQt5.Qt import QThread,  pyqtSignal # QMutex
import pandas as pd
import sys
from openpyxl import load_workbook #导入Excel工作表操作模块
import time



class Thread_Openfile(QThread):
    _signal=pyqtSignal()
    message_signal=pyqtSignal(str)
    data_signal=pyqtSignal(dict)
    propert_signal=pyqtSignal(int)
    def __init__(self,fileName,skiprows):
        super().__init__()
        self.fileName=fileName
        self.skiprows=skiprows
        
        
    def run(self):
        self.message_signal.emit('正在读取文件,请等待!')
        dfs=pd.DataFrame()
        self.propert_signal.emit(2)
        try:
            wbook=load_workbook(self.fileName) #打开工作簿
            wsheets=wbook.get_sheet_names() #获取工作表
            self.propert_signal.emit(10)
            dfs=pd.read_excel(self.fileName,sheet_name=wsheets,skiprows=self.skiprows)
            message='已成功读取文件:{}'.format(self.fileName)
            
            self.data_signal.emit(dfs)
            
            self.message_signal.emit(message)
            self.propert_signal.emit(20)
        except BaseException as e:
            message=str(e)
            self.message_signal.emit(message)
            self.propert_signal.emit(0)
            
        finally:
            self._signal.emit()
            
        



class Thread_Concatfile(QThread):
    _signal=pyqtSignal()
    message_signal=pyqtSignal(str)
    data_signal=pyqtSignal(dict)
    propert_signal=pyqtSignal(int)
    
    
    def __init__(self,dfs,isChecked,lineEdit_dropindex):
        super().__init__()
        self.dfs=dfs
        self.isChecked=isChecked
        self.lineEdit_dropindex=lineEdit_dropindex
        
        
    def run(self):
        dfs=self.dfs
        df=pd.DataFrame()
        long=len(dfs.keys())
        for sheetname in dfs.keys():
            message='正在合并{}工作表……'.format(sheetname)
            self.message_signal.emit(message)
            tmp=dfs[sheetname]
            tmpdf=tmp.copy(deep=True)
            try:
                drop_list=[int(i) for i in self.lineEdit_dropindex.split(',')]
                tmpdf.drop(labels=None,axis=0, index=drop_list, columns=None, inplace=True) # 删除一行
            except BaseException as e:
                message='{}\n表:{} 删除行解析异常,不做删除!'.format(e,sheetname)
                self.message_signal.emit(message)
                drop_list=None
            tmpdf['SheetName']=sheetname
            try:
                if self.isChecked:
                    df=pd.concat([df,tmpdf],ignore_index=True,axis=0)
                else:
                    df=pd.concat([df,tmpdf],ignore_index=False,axis=0)
            except BaseException as e:
                message='合并{}工作表异常!'.format(sheetname)
                self.message_signal.emit(message)
                
            finally:
                self.propert_signal.emit(20+60/long)
                
                
        self._signal.emit()
        self.data_signal.emit({'df':df})
        self.propert_signal.emit(80)
        



class Thread_Contrasttitle(QThread):
    _signal=pyqtSignal()
    message_signal=pyqtSignal(str)
    data_signal=pyqtSignal(dict)
    propert_signal=pyqtSignal(int)
    
    def __init__(self,dfs):
        super().__init__()
        self.dfs=dfs
        
    def run(self):
        dfs=self.dfs
        try:
            i=0
            long=len(dfs.keys())
            for sheetname in dfs.keys():
                i+=1
                tmpdf=dfs[sheetname]
                c0=list(tmpdf.columns)
                tmpdfc0=pd.DataFrame([[c0[i],'√'] for i in range(len(c0))],columns=['columns',sheetname])
                self.propert_signal.emit(20+30/long)
                if i==1:
                    df=tmpdfc0
                else:
                    df = pd.merge(df,tmpdfc0,how='outer',on='columns')
            self.df=df
    
            message='工作表标题对比完成!'
            self.message_signal.emit(message)
            
            
        except BaseException as e:
            message='{}\n工作表对比失败!'.format(e)
            self.message_signal.emit(message)
        finally:
            
                
            self._signal.emit()
            self.data_signal.emit({'df':df})
            self.propert_signal.emit(50)


        
        
class Thread_Savefile(QThread):
    _signal=pyqtSignal()
    message_signal=pyqtSignal(str)
    propert_signal=pyqtSignal(int)
    def __init__(self,df,isChecked,fileName):
        super().__init__()
        self.df=df
        self.isChecked=isChecked
        self.fileName=fileName
        
    def run(self):
        self._signal.emit()  
        df=self.df
        try:
            if self.isChecked:
                df.to_excel(self.fileName,index=True)
            else:
                df.to_excel(self.fileName,index=False)
            message='文件已保存至:{}'.format(self.fileName)
            self.message_signal.emit(message)
            
        except BaseException as e:
            message='{}\n文件{}保存失败!'.format(e,self.fileName)
        finally:    
            self.propert_signal.emit(100)




class Ui_Form(object):
    def setupUi(self, Form):
        Form.setObjectName("Form")
        Form.resize(376, 276)
        self.gridLayout_2 = QtWidgets.QGridLayout(Form)
        self.gridLayout_2.setObjectName("gridLayout_2")
        self.groupBox_operate = QtWidgets.QGroupBox(Form)
        self.groupBox_operate.setObjectName("groupBox_operate")
        self.gridLayout_4 = QtWidgets.QGridLayout(self.groupBox_operate)
        self.gridLayout_4.setObjectName("gridLayout_4")
        self.pushButton_openfile = QtWidgets.QPushButton(self.groupBox_operate)
        self.pushButton_openfile.setObjectName("pushButton_openfile")
        self.gridLayout_4.addWidget(self.pushButton_openfile, 0, 0, 1, 1)
        self.pushButton_merge = QtWidgets.QPushButton(self.groupBox_operate)
        self.pushButton_merge.setObjectName("pushButton_merge")
        self.gridLayout_4.addWidget(self.pushButton_merge, 0, 1, 1, 1)
        self.pushButton_contrast = QtWidgets.QPushButton(self.groupBox_operate)
        self.pushButton_contrast.setObjectName("pushButton_contrast")
        self.gridLayout_4.addWidget(self.pushButton_contrast, 1, 0, 1, 1)
        self.pushButton_savefile = QtWidgets.QPushButton(self.groupBox_operate)
        self.pushButton_savefile.setObjectName("pushButton_savefile")
        self.gridLayout_4.addWidget(self.pushButton_savefile, 1, 1, 1, 1)
        self.progressBar = QtWidgets.QProgressBar(self.groupBox_operate)
        self.progressBar.setProperty("value", 0)
        self.progressBar.setObjectName("progressBar")
        self.gridLayout_4.addWidget(self.progressBar, 2, 0, 1, 2)
        self.gridLayout_2.addWidget(self.groupBox_operate, 0, 1, 1, 1)
        self.gridLayout = QtWidgets.QGridLayout()
        self.gridLayout.setObjectName("gridLayout")
        self.groupBox_set = QtWidgets.QGroupBox(Form)
        self.groupBox_set.setObjectName("groupBox_set")
        self.gridLayout_3 = QtWidgets.QGridLayout(self.groupBox_set)
        self.gridLayout_3.setObjectName("gridLayout_3")
        self.lineEdit_skiprows = QtWidgets.QLineEdit(self.groupBox_set)
        self.lineEdit_skiprows.setObjectName("lineEdit_skiprows")
        self.gridLayout_3.addWidget(self.lineEdit_skiprows, 0, 1, 1, 2)
        self.lineEdit_dropindex = QtWidgets.QLineEdit(self.groupBox_set)
        self.lineEdit_dropindex.setObjectName("lineEdit_dropindex")
        self.gridLayout_3.addWidget(self.lineEdit_dropindex, 1, 1, 1, 2)
        self.checkBox_ignore = QtWidgets.QCheckBox(self.groupBox_set)
        self.checkBox_ignore.setObjectName("checkBox_ignore")
        self.gridLayout_3.addWidget(self.checkBox_ignore, 2, 0, 1, 2)
        self.checkBox_index = QtWidgets.QCheckBox(self.groupBox_set)
        self.checkBox_index.setObjectName("checkBox_index")
        self.gridLayout_3.addWidget(self.checkBox_index, 2, 2, 1, 1)
        self.label_skiprows = QtWidgets.QLabel(self.groupBox_set)
        self.label_skiprows.setObjectName("label_skiprows")
        self.gridLayout_3.addWidget(self.label_skiprows, 0, 0, 1, 1)
        self.label_dropindex = QtWidgets.QLabel(self.groupBox_set)
        self.label_dropindex.setObjectName("label_dropindex")
        self.gridLayout_3.addWidget(self.label_dropindex, 1, 0, 1, 1)
        self.gridLayout.addWidget(self.groupBox_set, 0, 0, 1, 1)
        self.gridLayout_2.addLayout(self.gridLayout, 0, 0, 1, 1)
        self.groupBox_message = QtWidgets.QGroupBox(Form)
        self.groupBox_message.setObjectName("groupBox_message")
        self.gridLayout_5 = QtWidgets.QGridLayout(self.groupBox_message)
        self.gridLayout_5.setObjectName("gridLayout_5")
        self.textBrowser = QtWidgets.QTextBrowser(self.groupBox_message)
        self.textBrowser.setObjectName("textBrowser")
        self.gridLayout_5.addWidget(self.textBrowser, 0, 0, 1, 1)
        self.gridLayout_2.addWidget(self.groupBox_message, 1, 0, 1, 2)

        self.retranslateUi(Form)
        # 槽
        self.pushButton_openfile.clicked.connect(self.open_file)
        self.pushButton_merge.clicked.connect(self.concat_file)
        self.pushButton_contrast.clicked.connect(self.contrast_title)
        self.pushButton_savefile.clicked.connect(self.save_file)
        
        self.checkBox_ignore.stateChanged.connect(self.change_ignore) # 变更时调用函数
        self.checkBox_index.stateChanged.connect(self.change_index) # 变更时调用函数
        
        QtCore.QMetaObject.connectSlotsByName(Form)
        

    def retranslateUi(self, Form):
        _translate = QtCore.QCoreApplication.translate
        Form.setWindowTitle(_translate("Form", "Excel工作表合并"))
        self.groupBox_operate.setTitle(_translate("Form", "操作"))
        self.pushButton_openfile.setText(_translate("Form", "选择文件"))
        self.pushButton_merge.setText(_translate("Form", "合并文件"))
        self.pushButton_contrast.setText(_translate("Form", "标题对比"))
        self.pushButton_savefile.setText(_translate("Form", "保存文件"))
        self.groupBox_set.setTitle(_translate("Form", "设置"))
        self.checkBox_ignore.setText(_translate("Form", "重塑索引"))
        self.checkBox_index.setText(_translate("Form", "写入索引"))
        self.label_skiprows.setText(_translate("Form", "跳过行"))
        self.label_dropindex.setText(_translate("Form", "删除行"))
        self.groupBox_message.setTitle(_translate("Form", "消息"))
        
        self.lineEdit_skiprows.setText(_translate("Form", "0"))
        self.lineEdit_dropindex.setText(_translate("Form", "0"))
        self.checkBox_ignore.setChecked(True)
        


    def change_ignore(self):
        if self.checkBox_ignore.isChecked():
            message='重构索引列:是!'
            self.show_message(message)
        else:
            message='重构索引列:否!'
            self.show_message(message)

            
    def change_index(self):
        if self.checkBox_index.isChecked():
            message='写入索引列:是!'
            self.show_message(message)
        else:
            message='写入索引列:否!'
            self.show_message(message)
            
            
    def show_message(self,message):
        self.textBrowser.append('{} {}'.format(time.strftime('%Y-%m-%d %H:%M:%S'),message))# 追加文本
        
    def set_btn(self):
        self.pushButton_openfile.setEnabled(True)
        self.pushButton_merge.setEnabled(True)
        self.pushButton_contrast.setEnabled(True)
        self.pushButton_savefile.setEnabled(True)
        
    def stop_btn(self):
        self.pushButton_openfile.setEnabled(False)
        self.pushButton_merge.setEnabled(False)
        self.pushButton_contrast.setEnabled(False)
        self.pushButton_savefile.setEnabled(False)
        
    
    def open_file(self):
        # getOpenFileName(parent: QWidget = None, caption: str = '', directory: str = '', filter: str = '', initialFilter: str = '', options: Union[QFileDialog.Options, QFileDialog.Option] = 0)
        fileName, filetype=QFileDialog.getOpenFileName(caption='选择Excel文件',directory='./',filter='*.xlsx')
        
        if fileName:
            message='选择的文件为:{}'.format(fileName)
            self.show_message(message)
            
            skiprows=int(self.lineEdit_skiprows.text())# 跳过行
            self.stop_btn()
            self.thread_openfile=Thread_Openfile(fileName, skiprows)
            self.thread_openfile._signal.connect(self.set_btn)
            self.thread_openfile.message_signal.connect(self.show_message)
            self.thread_openfile.data_signal.connect(self.get_dfs)
            self.thread_openfile.propert_signal.connect(self.set_propert)
            self.thread_openfile.start()
        else:
            self.show_message('文件选取无效!请重新选择。')
    
    def get_dfs(self,dfs):
        self.dfs=dfs
        
        
        
    def get_df(self,df):
        self.df=df['df']# 字典df内容解析
        
        

    def set_propert(self,value):
        self.progressBar.setProperty("value", value)

    def concat_file(self):
        '''合并'''

        df=pd.DataFrame()
        try:
            dfs=self.dfs
        except BaseException as e:
            message='请先读取文件!'
            self.show_message(message)
            return None
        
        
        isChecked=self.checkBox_ignore.isChecked()
        lineEdit_dropindex=self.lineEdit_dropindex.text()
        self.stop_btn()
        self.thread_concatfile=Thread_Concatfile(dfs,isChecked,lineEdit_dropindex)
        self.thread_concatfile._signal.connect(self.set_btn)
        self.thread_concatfile.message_signal.connect(self.show_message)
        self.thread_concatfile.data_signal.connect(self.get_df)
        self.thread_concatfile.propert_signal.connect(self.set_propert)
        self.thread_concatfile.start()
        
        
        
    
    def contrast_title(self):
        '''对比'''

        try:
            dfs=self.dfs
        except BaseException as e:
            self.show_message('请先读取文件!')
            return None

        self.stop_btn()
        self.thread_contrasttitle=Thread_Contrasttitle(dfs)
        self.thread_contrasttitle._signal.connect(self.set_btn)
        self.thread_contrasttitle.message_signal.connect(self.show_message)
        self.thread_contrasttitle.data_signal.connect(self.get_df)
        self.thread_contrasttitle.propert_signal.connect(self.set_propert)
        self.thread_contrasttitle.start()


        
    def save_file(self):
        '''保存'''
        try:
            df=self.df
        except BaseException as e:
            self.show_message('请先对文件内容进行合并或者对比!')
            return None
        
        fileName, filetype = QFileDialog.getSaveFileName(caption='保存文件',directory='./',filter='*.xlsx')
        
        if fileName:
            self.show_message('文件将保存至:{}'.format(fileName))
            
            isChecked=self.checkBox_index.isChecked()
            
            self.stop_btn()
            self.thread_savefile=Thread_Savefile(df,isChecked,fileName)
            self.thread_savefile._signal.connect(self.set_btn)
            self.thread_savefile.message_signal.connect(self.show_message)
            self.thread_savefile.propert_signal.connect(self.set_propert)
            self.thread_savefile.start()
        else:
            self.show_message('保存无效!请重新保存文件。')
        
        



if __name__ == "__main__":
    app = QtWidgets.QApplication(sys.argv)
    Form = QtWidgets.QWidget()
    ui = Ui_Form()
    ui.setupUi(Form)
    Form.show()
    sys.exit(app.exec_())

程序打包

在控制台执行命令

pyinstaller -i .\icon\excel.ico -F .\工作表合并多线程.py -w


演示多线程程序


最近发表
标签列表