Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/python-3.x/15.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 使用tkinter和openpyxl迭代电子表格的最佳方法?_Python_Python 3.x_Optimization_Tkinter_Openpyxl - Fatal编程技术网

Python 使用tkinter和openpyxl迭代电子表格的最佳方法?

Python 使用tkinter和openpyxl迭代电子表格的最佳方法?,python,python-3.x,optimization,tkinter,openpyxl,Python,Python 3.x,Optimization,Tkinter,Openpyxl,我是一个完全的Python初学者,尝试制作一个GUI,允许用户选择一个Excel文件,从中提取和分析一些数据。对于GUI,我使用tkinter,对于Excel操作,我使用openpyxl我目前拥有的代码可以工作,但是当选择的Excel文件很大时,运行时会非常长(一个10000行x20列的电子表格需要大约一个小时的迭代时间,而且随着时间的推移会变得越来越慢)。此外,GUI在迭代过程中会停止响应。我以前使用MATLAB编写的程序实际上是相同的,它工作得很好,整个迭代过程只需一两秒钟,所以这里的某些东

我是一个完全的Python初学者,尝试制作一个GUI,允许用户选择一个Excel文件,从中提取和分析一些数据。对于GUI,我使用tkinter,对于Excel操作,我使用openpyxl我目前拥有的代码可以工作,但是当选择的Excel文件很大时,运行时会非常长(一个10000行x20列的电子表格需要大约一个小时的迭代时间,而且随着时间的推移会变得越来越慢)。此外,GUI在迭代过程中会停止响应。我以前使用MATLAB编写的程序实际上是相同的,它工作得很好,整个迭代过程只需一两秒钟,所以这里的某些东西肯定很奇怪。现在我知道这是我的问题,而不是Python的问题,所以我希望你们能帮助我找到解决问题的正确方向

下面是一些我正在使用的简化示例,以帮助说明我的情况。我需要检查电子表格的每一行,检查该行中的某个值,看它是否符合我的要求,如果符合,我将存储该行中的一些数据

wb = openpyxl.load_workbook(filename = 'some_garbage.xlsx', read_only=True).worksheets[0]
all_data = wb.cell
desiredColor = 'Purple'
foodStorage = []

for row in range(2, wb.max_row + 1):
    print(row)
    if(all_data(row, 1).value == desiredColor):
        foodStorage.append(all_data(row,2))
        print('I found purple! Yee')

我应该使用openpyxl以外的模块来完成此任务,还是我只是犯了一些错误,使openpyxl无法充分发挥其潜力? 我应该使用线程来加速迭代过程,还是确保我的GUI窗口在迭代进行时不会完全“无响应”?


我试图寻找与类似问题相关的问题,但我并没有真正找到我想要的,很可能是因为我缺乏用恰当的语言表达问题的能力。因此,我提前为我提出的问题道歉,这些问题可能已经被回答过一百万次了。我非常感谢您能提供的任何帮助,感谢您的时间。

我正在做类似的工作,但数据量更大

我有一个类似的问题,我认为这是因为处理器试图在同一个线程上运行excel迭代和root.mainloop(),这不仅减慢了进程,而且还挂起了应用程序,使GUI没有响应。要使其正常工作,必须在与root.mainloop()不同的线程中调用worker(迭代)函数。最好的方法是为GUI、Worker和应用程序定义多个类,并在GUI在不同循环中运行时从应用程序类调用Worker函数线程

一个同样的简单样本-

import tkinter as tk
from tkinter import ttk,messagebox
import threading
import time

#base GUI Class
class GUI:
    def __init__(self, root, runCommand):
        mf = ttk.Frame(root, padding="5 5 5 5")
        mf.grid(column=0, row=0)
        mf.columnconfigure(0, weight=1)
        mf.rowconfigure(0, weight=1)

        # Global Values
        self.Fnm = tk.StringVar(root, "SearchFile.xlsx")
        self.Ncol = tk.StringVar(root, "D")
        self.Vcol = tk.StringVar(root, "C")
        # Label
        tk.Label(mf, text="File Name").grid(column=1, row=1, pady=6)
        tk.Label(mf, text="Name Col").grid(column=1, row=3, pady=6)
        tk.Label(mf, text="Value Col").grid(column=3, row=3, pady=6)

        # components
        self.fname = ttk.Entry(mf, width=18, textvariable=self.Fnm)
        self.nmCol = ttk.Entry(mf, width=6, textvariable=self.Ncol)
        self.valCol = ttk.Entry(mf, width=6, textvariable=self.Vcol)
        self.but = ttk.Button(mf, text="Refresh", command=runCommand)
        self.pgbar = ttk.Progressbar(mf, orient="horizontal", mode="determinate")

        # Design
        self.fname.grid(column=2, row=1, pady=3, columnspan=3)
        self.nmCol.grid(column=2, row=3, pady=3)
        self.valCol.grid(column=4, row=3, pady=3)
        self.but.grid(column=2, row=2, columnspan=2)
        self.pgbar.grid(column=1,row=4,columnspan=4)

    def refresh(self):
        pass

    def get(self):
        return [self.Fnm.get(), self.Ncol.get(), self.Vcol.get()]

#Base process Class
class Proc:
    def __init__(self, dets,pgbar,but):
        self.Fnm = dets[0]
        self.Ncol = dets[1]
        self.Vcol = dets[2]
        self.pg=pgbar
        self.butt=but

    def refresh(self):
        self.butt['state'] = 'disabled'
        self.pg.start()
        #ATTENTION:Enter Your process Code HERE
        for _ in range(5):
            time.sleep(2)#Longggg work
        self.pg.stop()
        #Any search/sort algorithm to be used
        #You can use self.pg.step() to be more specific for how the progress bar proceeds
        messagebox.showinfo("Process Done","Success")
        self.butt['state'] = 'enabled'

#Base Application Class
class App:
    def __init__(self, master):
        self.master = master
        self.gui = GUI(self.master, self.runit)

    def runit(self):
        self.search = Proc(self.gui.get(),self.gui.pgbar,self.gui.but)
        self.thread1 = threading.Thread(target=self.search.refresh)
        self.thread1.start()

def main():
    app = tk.Tk()
    gui = App(app)
    app.title("Refresh Search File")
    app.mainloop()

if __name__ == '__main__':
    main()
对于通过数据的迭代,您可以签出更高效的代码


我不能在这里写所有的代码,因为它太长了,所以请参考链接

您应该仔细检查
max\u row
的值。当我在我的一端使用它时,它返回电子表格的最大可能行,而不是最后一行。例如,我有一个4777行的电子表格,但是
max_row
返回了
65536行。它返回最后一行,正如我所期望的那样。也许这只是我们的电子表格之间的差异?这是一个常见的问题。存在多个bug报告。也就是说,如果它不影响你,那就好了。只需要找出问题所在。我想是因为栏目太多了。当我使用openpyxl时,我通常会将电子表格缩减到只需要比较的列,然后从中创建另一个包含所有数据的电子表格。否则,加载要读取的文件会花费很长时间,然后运行代码也会花费很长时间。当你说减少电子表格时,你的意思是你只是进入Excel并删除不需要的列吗?或者有没有办法指定openpyxl只关心某些列?我手动删除了我不想要的列。这帮助我将速度提高了20%到90%。这样做对我来说不是问题,但我相信如果你不需要这样做,那会更好。请不要在回答中没有提供基本概念的情况下链接到外部来源。如果出于任何原因,你的链接被破坏了,这个答案将不再对任何人有用。好吧@Mike SMT,我会在这里添加一些逻辑,但我真的会避免添加代码,它非常长,但是如果你说它可能更好,我不会介意。