Excel内容提取

静态文件 static 下载

import pandas as pd
# from pandasql import sqldf  # 用 SQL 语句操作 panda 模块
from pandasql import *  # 用 SQL 语句操作 panda 模块

import os  # 处理文件模块
import shutil  # 删除非空文件夹模块
import time
from PySide2.QtWidgets import QApplication, QMessageBox, QFileDialog, QMainWindow
from PySide2.QtUiTools import QUiLoader
from PySide2.QtGui import QIcon
from threading import Thread, Lock
from PySide2.QtCore import Signal, QObject

# 多线程处理

# 信号库
class SignalStore(QObject):
    # 定义一种信号
    progress_update = Signal(int,str)

    # 子线程让主线程弹窗
    msg = Signal(str)
    # 导入显示框添加内容信号



# 实例花
so = SignalStore()


def getTime():
    a = time.strftime('%H:%M:%S', time.localtime(time.time()))
    # return time.strftime('%Y-%m-%d %H:%M:%S',time.localtime(time.time()))
    return a


# 数据处理
class DataHandle:
    def __init__(self):
        self.ui = QUiLoader().load('static/web.ui')

        # 连接信号到处理的 slot 函数
        so.progress_update.connect(self.setProgress)

        so.msg.connect(self.son_msg)
        # 0. 按钮事件
        self.ui.pushButton.clicked.connect(self.changeFileExcel)  # 选择文件事件
        self.ui.pushButton_2.clicked.connect(self.to_begin)  # 开始提取事件
        self.fieldName = '' # 筛选字段名的内容
        self.content = '' # 筛选字段的内容
        self.num = 0 # 计数,提取到有内容的文件数量
        self.statistical = 0 # 所有文件条数汇总
        # 1. 选择文件夹路径,获取到文件夹下所有文件的绝对路径
        self.filePath = ''  # 选择的文件夹路径
        self.fileList = []  # 文件夹路径下所有文件的绝对路径集合
        self.fileName = []  # 文件名称集合
        self.excelPath = ''  # 当前文件的 excel 路径
        # 2. 开始依次读取 excel 文件,并进行处理


        self.i = 0
        self.bankLock = Lock()

        self.excel = ''  # 读取导入的表数据







    # 选择文件点击事件
    def changeFileExcel(self):

        self.fileName = []
        self.fileList= []
        self.filePath = QFileDialog.getExistingDirectory(QMainWindow(), "选择文件夹")
        print('文件夹路径', self.filePath)
        # 准备一个空列表,用来存储遍历数据

        ''' 
                root  :代表目录的路径
                dirs  :一个list,包含了dirpath下所有子目录文件夹的名字
                files :一个list,包含了所有非目录文件的名字
        '''
        for root, dirs, files in os.walk(self.filePath):
            # fileName.append()
            # 循环遍历列表:files【所有文件】,仅得到不包含路径的文件名
            for fileObj in files:
                # 空列表写入遍历的文件名称,兵勇目录路径拼接文件名称
                path = os.path.join(root, fileObj).replace('\\', '/')
                self.fileName.append(fileObj)
                self.fileList.append(path)

        print('文件名集合', self.fileName)
        print('文件路径集合', self.fileList)
        self.ui.textBrowser.setText(self.filePath)

    # 处理进度条的 slot 函数
    def setProgress(self, value,text):
        self.ui.progressBar_2.setValue(value)
        self.ui.textBrowser_2.append(text)

        if value == len(self.fileList):
            self.end_time = time.time()
            messageBox = QMessageBox()
            messageBox.setWindowTitle('提取结果')
            messageBox.setText(f'提取筛选内容成功,共<span style="color:red;font-weight:bold;">{self.num}</span>个文件,'
                               f'<span style="color:red;font-weight:bold;">{self.statistical}</span>条内容')
            messageBox.setStandardButtons(QMessageBox.Yes | QMessageBox.No)
            buttonY = messageBox.button(QMessageBox.Yes)
            buttonY.setText('打开提取结果文件夹')
            buttonN = messageBox.button(QMessageBox.No)
            buttonN.setText('退出')
            messageBox.exec_()

            if messageBox.clickedButton() == buttonY:
                # print('你选择了yes')
                start_directory = r'提取结果' # 打开文件夹提取结果
                os.startfile(start_directory)
            # if choice == QMessageBox.No:
            #     # print('你选择了no')
            #     pass

            # QMessageBox.information(
            #     self.ui,
            #     '成功',
            #     f'提取筛选内容成功,共<span style="color:red;font-weight:bold;">{self.num}</span>个文件')

    # 开始提取事件
    def to_begin(self):
        self.ui.pushButton_2.setEnabled(False)
        self.fieldName = self.ui.lineEdit.text()
        self.content = self.ui.lineEdit_2.text()
        print(self.fieldName)
        print(self.content)

        try:
            ml = os.getcwd() + '\\提取结果'  # 获取当前目录
            judge = os.path.exists(ml)  # 判断疑点数据文件夹是否存在,存在就删除重新创建
            if judge:
                shutil.rmtree(ml)
            os.mkdir(os.getcwd() + '\\提取结果')  # 创建疑点数据文件夹
            self.i = 0
        except PermissionError as e:
            e = str(e)
            self.msg('错误', e)
            return

        self.ui.progressBar_2.setRange(0, len(self.fileList))

        self.ui.progressBar_2.setValue(0)
        self.ui.textBrowser_2.append(f'开始提取数据{getTime()}')
        self.num = 0
        self.statistical = 0
        for i,item in enumerate(self.fileList):
            sql = f"""select * from tables where `{self.fieldName}` like '%{self.content}%'"""
            self.i = self.i + 1

            dataQuery_son = Thread(target=self.dataQuery, args=(item,self.fileName[i], sql))
            dataQuery_son.setDaemon(True)  # 设置成守护线程,主程序退出,线程也结束
            dataQuery_son.start()
            dataQuery_son.join()
            so.progress_update.emit(self.i, f'提取文件:{self.fileName[i]} 完成')
        self.ui.pushButton_2.setEnabled(True)

    # 对数据表 self.excel 进行查询处理
    def dataQuery(self,item, excelName, q):
        self.bankLock.acquire()
        try:
            self.excelPath = item
            print('文件路径', self.excelPath)
            tableArr = self.excelPath.split(".")
            print("文件类型", tableArr[-1])
            if tableArr[-1] == "csv":
                try:
                    print('读取的csv')
                    ex = pd.read_csv(self.excelPath, encoding='ANSI', keep_default_na=False, low_memory=False, sep=',')

                # labels = list(ex.columns.values)
                # print('表头',labels)
                except BaseException as e:
                    e = str(e)
                    so.msg.emit(f'错误,读取 csv 出现问题:{e}')
                    self.toin = 1  # 让导入计时停止
                    # self.ui.pushButton_3.setEnabled(True)
                    return

            else:
                ex = pd.read_excel(self.excelPath, keep_default_na=False)
                print('读取的excel')

            # 将 excel 读成表格形式, excel 就是要操作的数据表
            excel = pd.DataFrame(ex)

            a = list(excel.keys())

            # a = sorted(a, key=lambda i: len(i))  # 将表头按字符串长度进行排序
            self.tableTitle = a
            print("导入的表头", a)
            print('table数据', excel)
            global tables
            tables = excel



            pysqldf = lambda sql: sqldf(sql, globals())  # 为了避免每次都要传入dataframes,可以定义一个lambda

            sql = q
            # try:
            df = pysqldf(sql)  # 执行 sql


            print(f'表名{excelName}\n'
                  f'列数:{df.shape[1]}\n'
                  f'行数:{df.shape[0]}')
            self.statistical += df.shape[0]
            # 如果查出来没有数据,则代表没有该项错误,不需要生成 excel 表
            if df.shape[0] > 0:
                # self.errorNum += 1  # 增加一种错误类型计数
                thePath = os.getcwd() + '\\提取结果'  # 获取存取路径
                # writer = pd.ExcelWriter(thePath + f'\\{excelName}.csv')  # 创建错误数据 excel
                name = excelName.split('.')[0]
                writer = thePath + f'\\{name}.csv'  # 创建错误数据 excel
                # 将容易变成科学计数法的列保存为字符串
                for item in self.tableTitle:
                    # df[item] = '="' + df[item].apply(str) + '"'
                    df[item] = df[item].apply(str) + '\t'


                df.to_csv(writer, float_format='{:f}'.format, columns=self.tableTitle, index=False, sep=',',
                          encoding='ANSI')
                self.num += 1






        except BaseException as e:
            print('错误', e)
            e = '存在异常:' + str(e)
            # so.progress_update.emit(self.i,e)
            print("存在异常", e)  # 打印所有异常

            # self.bankLock.release()
            # return
        self.bankLock.release()



    # over





    # 子线程让主线程弹窗,表头有误
    def son_msg(self, str):
        arr = str.split(',')
        print("arr", len(arr), arr[1])
        QMessageBox.critical(
            self.ui,
            arr[0],
            arr[1]
        )

    # 弹框
    def msg(self, info, text):
        QMessageBox.critical(
            self.ui,
            info,
            text
        )




if __name__ == '__main__':
    # thread = Thread(target=DataHandle)
    # thread.start()

    app = QApplication([])
    # 加载 icon
    app.setWindowIcon(QIcon("static/logo.ico"))
    handle = DataHandle()
    handle.ui.show()

    app.exec_()

 

posted @ 2022-05-24 14:50  彬彬有礼丶林  阅读(286)  评论(0)    收藏  举报