在python中将文件保存到excel时如何显示进度栏? [英] How to show progress bar while saving file to excel in python?

查看:65
本文介绍了在python中将文件保存到excel时如何显示进度栏?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

感谢您能为我提供帮助.将文件保存到excel时出现进度栏时遇到麻烦.我想要实现的是显示一个进度条,同时从 pandas数据框 qwidgettable 保存excel文件,因为保存之前需要一些时间.在Excel文件被下载或保存之前,我要关闭进度条.我尝试查看网络,但看不到查询的具体答案.到目前为止,这是我创建的已编译代码.

Appreciate if you could help me. I have a trouble showing up the progress bar while saving file to excel. What I want to achieve is to show a progress bar while saving excel file from a pandas dataframe also from qwidgettable as it takes time before it saves. Until the excel file is downloaded or saved i want that progress bar to close. I tried looking over the net but I cant see specific answers to my query. So far, this is the compiled codes I have created.

import sys
from PyQt5 import QtWidgets, QtCore
import pandas as pd
import time
import psutil


class ThreadClass(QtCore.QThread):
   updateProgressBar = QtCore.pyqtSignal(int)

   def __init__(self, parent=None):
       super(ThreadClass, self).__init__(parent)

   def run(self):
       while True:
           val = int(psutil.cpu_percent())
           time.sleep(1)
           self.updateProgressBar.emit(val)

class Window(QtWidgets.QMainWindow):
    def __init__(self):
        super(Window, self).__init__()
        self.setGeometry(50,50,500,500)
        self.setWindowTitle('PyQt Tuts')
        self.table()

    def updateProgressBar(self, val):
        self.progressBar.setValue(val)

    def table(self):
        self.tableWidget = QtWidgets.QTableWidget()
        self.tableWidget.setGeometry(QtCore.QRect(220, 100, 411, 392))
        self.tableWidget.setColumnCount(2)
        self.tableWidget.setRowCount(5)
        self.tableWidget.show()

        item = QtWidgets.QTableWidgetItem()
        item.setText("Amount")
        self.tableWidget.setHorizontalHeaderItem(1, item)

        records = [
            ['Product 1', 1000],
            ['Product 2', 500],
            ['Product 3', 600],
            ['Product 4', 300],
            ['Product 5', 800],
        ]

        self.df = pd.DataFrame(records, columns=['Name', 'Amount'])

        for r in range(5):
            for c in range(2):
                table_item = str(self.df.iloc[r, c])
                self.tableWidget.setItem(r, c, QtWidgets.QTableWidgetItem(table_item))

        self.pb_extract = QtWidgets.QPushButton(self.tableWidget)
        self.pb_extract.setGeometry(QtCore.QRect(10, 200, 75, 23))
        self.pb_extract.clicked.connect(self.extract)
        self.pb_extract.setText("EXTRACT")
        self.pb_extract.show()

    def extract(self):
        self.lb_downloading = QtWidgets.QLabel(self.tableWidget)
        self.lb_downloading.setGeometry(QtCore.QRect(10, 270, 81, 16))
        self.lb_downloading.setText("Downloading..")
        self.lb_downloading.show()

        self.progressBar = QtWidgets.QProgressBar(self.tableWidget)
        self.progressBar.setGeometry(QtCore.QRect(10, 290, 171, 10))
        self.progressBar.show()

        self.threadclass = ThreadClass()
        self.threadclass.start()
        self.threadclass.updateProgressBar.connect(self.updateProgressBar)

        self.df.to_excel('Products.xlsx', index=False)
        print('Download complete!')

def run():
    app = QtWidgets.QApplication(sys.argv)
    app.setStyle("fusion")
    w = Window()
    sys.exit(app.exec_())

run()

这些代码如下:

我要实现的是,当我单击提取按钮时,下载进度条将关闭,直到完全下载/保存了excel文件为止.

what i want to achieve is when i click the extract button, the downloading progressbar will close until the excel file fully downloaded/saved.

(PS我只是获得 val = int(psutil.cpu_percent())的随机值,因为我也不知道在应用程序运行时仅使用哪个特定的代码/函数来显示对您来说,我有一个进度条在移动.)

(P.S i just get random values for val = int(psutil.cpu_percent()) because i also don't know what specific code/function to use while the app is running just to show to you that i have a progress bar moving.)

提前谢谢!

推荐答案

在SO中无数次地询问了这些类型的问题,并且在注释中多次解释了要求,并说明了在这种情况下的可能,在这种情况下是不可能的.因此,为避免重复同一件事,我将根据OP的问题在这篇文章中解释这个主题.

通常使用窗口小部件来显示和/或从用户那里获取信息,而QProgressBar首先要做的是,它显示进度信息,而不会不显示计算.

A widget in general is used to show and/or obtain information from the user, and a QProgressBar does the first thing, that is, it shows the progress information, it does not calculate it.

如果可以将任务细分为"n"个子任务,则可以计算进度,因为就总子任务的数量而言,这将等于已经完成的子任务的数量.

Progress can be calculated if the task can be subdivided into "n" subtasks, since it would be equivalent to the number of subtasks already done with respect to the number of total subtasks.

  • 例如,如果任务是将N KB文件上传到服务器,则每个子任务可以是1KB信息,因此进度将是:

  • For example if the task is to upload a N KB file to a server, then each subtask can be 1KB of information, so the progress would be:

progress = 100 * number_of_KB_submitted/number_of_KB_of_file

  • 另一个例子是,如果您必须复制n个文件,则进度为:

  • Another example would be if you have to copy n files, then the progress would be:

    progress = 100 * number_of_copied_files / number_of_total_files
    

  • 从以上显而易见,只有将任务细分为子任务才能计算进度,因此,如果无法细分任务,则无法计算进度.

    From the above it is obvious that progress can only be calculated if the task can be subdivided into subtasks, so if the task cannot be subdivided then it is impossible to calculate any progress.

    在将大熊猫保存在Excel中的情况下,很明显它不能细分为"n"个任务,因此将无法计算其进度.

    In the case of saving the pandas in an excel it is obvious that it cannot be subdivided into "n" tasks so it will be impossible to calculate its progress.

    在使用to_excel将大熊猫保存在excel中的情况下,很明显它无法细分为"n"个任务,因此将无法计算其进度.

    In the case of saving the pandas in an excel using to_excel it is obvious that it cannot be subdivided into "n" tasks so it will be impossible to calculate its progress.

    在这些情况下,一种解决方法是显示繁忙的QProgressBar:

    A workaround in those cases is to show a busy QProgressBar:

    progressbar.setRange(0, 0)
    

    在您的情况下:

    import sys
    from PyQt5 import QtWidgets, QtCore
    import pandas as pd
    import time
    
    import threading
    
    
    class ExcelWorker(QtCore.QObject):
        started = QtCore.pyqtSignal()
        finished = QtCore.pyqtSignal()
    
        def execute(self, df, filename):
            threading.Thread(target=self._execute, args=(df, filename), daemon=True).start()
    
        def _execute(self, df, filename):
            self.started.emit()
            df.to_excel(filename, index=False)
            self.finished.emit()
    
    
    class DownloaderProgressBar(QtWidgets.QWidget):
        def __init__(self, parent=None):
            super(DownloaderProgressBar, self).__init__(parent)
    
            self._progressbar = QtWidgets.QProgressBar()
    
            lay = QtWidgets.QVBoxLayout(self)
            lay.addWidget(QtWidgets.QLabel(self.tr("Downloading..")))
            lay.addWidget(self.progressbar)
    
        @property
        def progressbar(self):
            return self._progressbar
    
    
    class Window(QtWidgets.QMainWindow):
        def __init__(self):
            super(Window, self).__init__()
            self.setGeometry(50, 50, 500, 500)
            self.setWindowTitle("PyQt Tuts")
            self.create_table()
    
            self.create_progressbar()
            self.create_worker()
    
        def create_progressbar(self):
            self.downloader_progressbar = DownloaderProgressBar(self.tableWidget)
            self.downloader_progressbar.setGeometry(10, 270, 170, 80)
            self.downloader_progressbar.hide()
    
        def create_worker(self):
            self.worker = ExcelWorker()
            self.worker.started.connect(self.on_started)
            self.worker.finished.connect(self.on_finished)
    
        def create_table(self):
            self.tableWidget = QtWidgets.QTableWidget()
            self.tableWidget.setGeometry(QtCore.QRect(220, 100, 411, 392))
            self.tableWidget.setColumnCount(2)
            self.tableWidget.setRowCount(5)
            self.tableWidget.show()
    
            item = QtWidgets.QTableWidgetItem()
            item.setText("Amount")
            self.tableWidget.setHorizontalHeaderItem(1, item)
    
            records = [
                ["Product 1", 1000],
                ["Product 2", 500],
                ["Product 3", 600],
                ["Product 4", 300],
                ["Product 5", 800],
            ]
    
            self.df = pd.DataFrame(records, columns=["Name", "Amount"])
    
            for r in range(5):
                for c in range(2):
                    table_item = str(self.df.iloc[r, c])
                    self.tableWidget.setItem(r, c, QtWidgets.QTableWidgetItem(table_item))
    
            self.pb_extract = QtWidgets.QPushButton(self.tableWidget)
            self.pb_extract.setGeometry(QtCore.QRect(10, 200, 75, 23))
            self.pb_extract.clicked.connect(self.extract)
            self.pb_extract.setText("EXTRACT")
            self.pb_extract.show()
    
        def extract(self):
            self.worker.execute(self.df.copy(), "Products.xlsx")
            self.downloader_progressbar.show()
    
        @QtCore.pyqtSlot()
        def on_started(self):
            self.downloader_progressbar.progressbar.setRange(0, 0)
    
        @QtCore.pyqtSlot()
        def on_finished(self):
            self.downloader_progressbar.progressbar.setRange(0, 1)
    
    
    def run():
        app = QtWidgets.QApplication(sys.argv)
        app.setStyle("fusion")
        w = Window()
        sys.exit(app.exec_())
    
    
    run()
    

    这篇关于在python中将文件保存到excel时如何显示进度栏?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆