You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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: ''

问题原因

  1. 输入框被提前清空:update_record函数末尾直接清空了fl_spinbox和cnt_entry,导致后续调用save_record时读取不到用户输入的值。
  2. Treeview更新逻辑错误:save_record中用DataFrame的index更新Treeview,而非选中的Treeview项,逻辑完全错误。
  3. 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.27 23:48:09