Python 使用tkinter和openpyxl迭代电子表格的最佳方法?
我是一个完全的Python初学者,尝试制作一个GUI,允许用户选择一个Excel文件,从中提取和分析一些数据。对于GUI,我使用tkinter,对于Excel操作,我使用openpyxl我目前拥有的代码可以工作,但是当选择的Excel文件很大时,运行时会非常长(一个10000行x20列的电子表格需要大约一个小时的迭代时间,而且随着时间的推移会变得越来越慢)。此外,GUI在迭代过程中会停止响应。我以前使用MATLAB编写的程序实际上是相同的,它工作得很好,整个迭代过程只需一两秒钟,所以这里的某些东西肯定很奇怪。现在我知道这是我的问题,而不是Python的问题,所以我希望你们能帮助我找到解决问题的正确方向 下面是一些我正在使用的简化示例,以帮助说明我的情况。我需要检查电子表格的每一行,检查该行中的某个值,看它是否符合我的要求,如果符合,我将存储该行中的一些数据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编写的程序实际上是相同的,它工作得很好,整个迭代过程只需一两秒钟,所以这里的某些东
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,我会在这里添加一些逻辑,但我真的会避免添加代码,它非常长,但是如果你说它可能更好,我不会介意。