Tkinter点击按钮导出搜索项到Excel 搜索自动导出问题修复
问题根因
输入搜索内容时自动触发Excel导出,核心是两个问题:
- 事件绑定错误:输入框的键盘触发事件(或者搜索关联的
StringVar变量追踪事件)错误绑定了带导出逻辑的print_area函数,而非仅负责刷新列表的search函数,导致每次按键输入时直接执行了导出代码。 - 按钮未正确绑定事件:当前
Print按钮创建时未指定command参数,即使修复自动触发问题,手动点击按钮也不会执行导出逻辑。
另外现有代码还存在几个隐性bug:
- SQL查询用字符串拼接写法,存在SQL注入风险
- 遍历查询结果赋值
fName时,仅会取最后一条结果的姓名字段作为导出文件名,多结果场景下文件名错误且会覆盖文件 - 数据库连接、游标用完未关闭,长期运行会出现连接泄漏
- 若
excel_backup文件夹不存在,导出时会直接抛路径不存在的错误 print_area和search函数重复写了完全相同的数据库查询、Treeview刷新逻辑,代码冗余
修复方案
1. 修正事件绑定
检查输入框的事件绑定代码,确保<Key>事件仅绑定search函数,如果之前给self.var_search加过trace变量追踪,要移除绑定到print_area的回调:
# 正确的输入框绑定,仅绑定search刷新列表,不要绑print_area self.txt_search.bind("<Key>", self.search)
2. 给Print按钮绑定导出回调
注意command参数只传函数名,不要加括号(加括号会在窗口初始化时直接执行函数):
self.btn_print = Button(root,text="Print", font=("times new roman", 15), bg="red", fg="white", command=self.print_area) self.btn_print.pack()
3. 重构优化代码,修复隐性bug
抽离公共查询逻辑,避免重复代码,同时修复其他问题:
import os import pandas as pd import pymysql from tkinter import messagebox, END # 初始化时先创建备份文件夹,避免路径不存在报错 if not os.path.exists("excel_backup"): os.makedirs("excel_backup") # 抽离公共的查询方法,避免重复写数据库连接逻辑 def fetch_search_data(self): con = pymysql.connect(host='localhost', user='root', password='', db='philanthropy') cur = con.cursor() # 用参数化查询避免SQL注入 search_key = self.var_search.get() cur.execute("select * from istavrity where familycode LIKE %s", (f"%{search_key}%",)) rows = cur.fetchall() # 关闭游标和连接 cur.close() con.close() return rows # 搜索函数仅负责刷新Treeview def search(self, ev): try: rows = self.fetch_search_data() self.employee_tree.delete(*self.employee_tree.get_children()) for i in rows: self.employee_tree.insert('', END, values=i) except Exception as ex: messagebox.showerror("Error", f"Error due to {str(ex)}") # 导出函数仅负责点击按钮后的导出逻辑 def print_area(self): try: rows = self.fetch_search_data() if len(rows) == 0: messagebox.showinfo("提示", "没有可导出的搜索结果") return columns = ('S.N.', 'Family Code', 'Family Name', 'Ritwik', 'Swastyayani', 'Family Name', 'Ritwik', 'Swastyayani', 'FamilyCode', 'Family Name', 'Ritwik', 'Swastyayani', 'FamilyCode', 'Family Name', 'Ritwik', 'Swastyayani', 'ravv') # 组合文件名,避免多结果场景下文件覆盖 first_fname = rows[0][1] search_key = self.var_search.get() treeview_df = pd.DataFrame(rows, columns=columns) save_path = f"excel_backup/{search_key}_{first_fname}.xlsx" # 导出时取消pandas默认索引列 treeview_df.to_excel(save_path, index=False) messagebox.showinfo("成功", f"导出完成,文件保存至:{save_path}") except Exception as ex: messagebox.showerror("Error", f"Error due to {str(ex)}")
如果需要导出前同步刷新Treeview的展示结果,可以在
print_area里调用self.search(None)复用刷新逻辑,不用重复写节点插入代码。
内容的提问来源于stack exchange,提问作者Ravi Katuwal
相关产品推荐
相关产品推荐

