Tkinter Entry组件值无法读取并写入Excel问题求助
Tkinter程序Excel写入报错问题
问题现象
update_record函数可正常更新Treeview组件,但调用save_record函数读取fl_spinbox和cnt_entry的值写入Excel时,触发ValueError: invalid literal for int() with base 10: ''错误。调试打印显示这两个组件的值为空,尽管Treeview已显示更新后的值,但无法同步到Excel。
相关代码
可正常运行的Treeview更新函数
def update_record(): # Grab record number selected = my_tree.focus() # Update Record # my_tree.item(selected, text="", values=(fl_spinbox.get(), cnt_entry.get(),)) # my_tree.item(selected, text="", values=(record[5], record[6],)) my_tree.set(selected, "fenceLabel", fl_spinbox.get()) my_tree.set(selected, "Comment",cnt_entry.get()) # Insert row into treeview my_tree.insert('', tk.END, values=fl_spinbox) my_tree.insert('', tk.END, values=cnt_entry) # Clear entry boxes fl_spinbox.delete(0, END) cnt_entry.delete(0, END)#
报错的Excel写入函数
def save_record(): excel_file = "fallers_output.xlsx" faller_file = Path.cwd() / excel_file # Set Output file df = pd.read_excel(faller_file) # Get primary key to use against df selected = my_tree.focus() if selected: primary_key = my_tree.item(selected)['values'][0] if primary_key in df["fallerId"].values: # Get the index of the row with the primary key index = df.index[df["fallerId"] == int(primary_key)] # Get button entry values new_fl_value = fl_spinbox.get() new_cnt_value = cnt_entry.get() print("Age string:", fl_spinbox.get()) # Debug print print("ID:", cnt_entry.get()) # Debug print df.at[index, "fenceLabel"] = int(new_fl_value) df.at[index, "Comment"] = new_cnt_value # Write to excel df.to_excel(faller_file, index=False) messagebox.showinfo("Success", "Values replaced and saved to Excel file successfully!") # Update Treeview display my_tree.item(index, values=(new_fl_value, new_cnt_value)) # Update displayed values fl_spinbox.delete(0, tk.END) cnt_entry.delete(0, tk.END) else: messagebox.showerror("Error", "Primary key not found in DataFrame")
组件初始化代码
fl_label.grid(row=0, column=2, padx=10, pady=10) fl_spinbox = ttk.Spinbox(data_frame, from_=1, to=27) fl_spinbox.insert(0, "1-27") fl_spinbox.grid(row=0, column=3, padx=5, pady=5, sticky="ew")
cnt_label = Label(data_frame, text="Comment") cnt_label.grid(row=0, column=4, padx=10, pady=10) cnt_entry = Entry(data_frame) cnt_entry.grid(row=0, column=5, padx=10, pady=10)
报错信息
<ipython-input-8-e0949f9e101c>:109: FutureWarning: Series.__getitem__ treating keys as positions is deprecated. In a future version, integer keys will always be treated as labels (consistent with DataFrame behavior). To access a value by position, use `ser.iloc[pos]` my_tree.insert(parent='', index='end', iid=count, text='', values=(record[0], record[3], record[4], record[8], record[13], record[15], record[16], record[17]), tags=('evenrow',)) <ipython-input-8-e0949f9e101c>:111: FutureWarning: Series.__getitem__ treating keys as positions is deprecated. In a future version, integer keys will always be treated as labels (consistent with DataFrame behavior). To access a value by position, use `ser.iloc[pos]` my_tree.insert(parent='', index='end', iid=count, text='', values=(record[0], record[3], record[4], record[8], record[13], record[15], record[16], record[17]), tags=('oddrow',)) Age string: ID: Exception in Tkinter callback Traceback (most recent call last): File "c:\Users\evaughan\AppData\Local\miniconda3\envs\fallers\Lib\tkinter\__init__.py", line 1967, in __call__ return self.func(*args) ^^^^^^^^^^^^^^^^ File "c:\Users\evaughan\AppData\Local\miniconda3\envs\fallers\Lib\site-packages\customtkinter\windows\widgets\ctk_button.py", line 554, in _clicked self._command() File "<ipython-input-12-5f1b7a09a2d5>", line 27, in save_record df.at[index, "fenceLabel"] = int(new_fl_value) ^^^^^^^^^^^^^^^^^ ValueError: invalid literal for int() with base 10: ''
问题原因
- 输入框被提前清空:
update_record函数末尾直接清空了fl_spinbox和cnt_entry,导致后续调用save_record时读取不到用户输入的值。 - Treeview更新逻辑错误:
save_record中用DataFrame的index更新Treeview,而非选中的Treeview项,逻辑完全错误。 - Spinbox初始值不合法:初始插入的
"1-27"是字符串,若用户未修改直接保存,也会触发类型转换错误。
解决方案
1. 调整输入框清空时机
移除update_record中的清空操作,改为在save_record成功保存后再清空:
def update_record(): selected = my_tree.focus() my_tree.set(selected, "fenceLabel", fl_spinbox.get()) my_tree.set(selected, "Comment", cnt_entry.get()) # 移除此处的清空代码 # fl_spinbox.delete(0, END) # cnt_entry.delete(0, END)
2. 从Treeview读取已更新的值
避免依赖输入框,直接从Treeview获取最新值进行保存:
def save_record(): excel_file = "fallers_output.xlsx" faller_file = Path.cwd() / excel_file df = pd.read_excel(faller_file) selected = my_tree.focus() if selected: item_values = my_tree.item(selected)['values'] primary_key = item_values[0] # 根据实际列索引获取fenceLabel和Comment的值 new_fl_value = item_values[5] # 替换为你的fenceLabel所在列索引 new_cnt_value = item_values[6] # 替换为你的Comment所在列索引 if primary_key in df["fallerId"].values: index = df.index[df["fallerId"] == int(primary_key)] # 验证值有效性 if not new_fl_value: messagebox.showerror("Error", "fenceLabel值不能为空") return try: fl_int = int(new_fl_value) except ValueError: messagebox.showerror("Error", "fenceLabel必须是整数") return df.at[index, "fenceLabel"] = fl_int df.at[index, "Comment"] = new_cnt_value df.to_excel(faller_file, index=False) messagebox.showinfo("Success", "保存成功!") # 保存后清空输入框 fl_spinbox.delete(0, END) cnt_entry.delete(0, END) else: messagebox.showerror("Error", "主键不存在于DataFrame中") else: messagebox.showerror("Error", "请先选择一条记录")
3. 修正Spinbox初始值
将初始值改为合法整数,避免格式错误:
fl_spinbox = ttk.Spinbox(data_frame, from_=1, to=27) fl_spinbox.insert(0, "1") # 替换原"1-27"为合法整数 fl_spinbox.grid(row=0, column=3, padx=5, pady=5, sticky="ew")
4. 修复Treeview更新逻辑
save_record中更新Treeview时,使用选中的项而非DataFrame的index:
# 替换原错误代码 my_tree.item(selected, values=(new_fl_value, new_cnt_value))
内容的提问来源于stack exchange,提问作者Eoin Vaughan
相关产品推荐
相关产品推荐

