繁体   English   中英

如何在 python 中将文件保存到 excel 时显示进度条?

[英]How to show progress bar while saving file to excel in python?

感谢您能帮助我。 将文件保存到 excel 时无法显示进度条。 我想要实现的是在从pandas dataframe qwidgettable保存 excel 文件的同时显示进度条,因为它需要时间才能保存。 在下载或保存 excel 文件之前,我希望该进度条关闭。 我试着在网上查看,但我看不到我的查询的具体答案。 到目前为止,这是我创建的编译代码。

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 文件完全下载/保存。

(PS 我只是得到val = int(psutil.cpu_percent())的随机值,因为我也不知道在应用程序运行时要使用什么特定代码/函数,只是为了向您显示我有一个进度条在移动。 )

先感谢您!

这些类型的问题在 SO 中已经被问过无数次,并且在评论中已经多次解释了这些要求,解释了在哪种情况下可以,在哪些情况下不可以。 所以为了避免重复同样的事情,我将根据 OP 的问题在这篇文章中解释这个主题。

一个小部件通常用于显示和/或从用户那里获取信息,QProgressBar 做第一件事,即显示进度信息,它不计算它

如果可以将任务细分为“n”个子任务,则可以计算进度,因为它相当于已经完成的子任务数量相对于总子任务的数量。

  • 例如,如果任务是上传一个 N KB 文件到服务器,那么每个子任务可以是 1KB 的信息,所以进度为:

     progress = 100 * number_of_KB_submitted/number_of_KB_of_file
  • 另一个例子是如果你必须复制 n 个文件,那么进度是:

     progress = 100 * number_of_copied_files / number_of_total_files

从上面可以看出,只有任务可以细分为子任务,才能计算进度,所以如果任务不能细分,就不可能计算任何进度。

在将 pandas 保存在 excel 中的情况下,显然不能将其细分为“n”个任务,因此无法计算其进度。

在使用 to_excel 将 pandas 保存在 excel 中的情况下,很明显它不能细分为“n”个任务,因此无法计算其进度。

在这些情况下的解决方法是显示一个繁忙的 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()

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM