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

基于Tkinter的Excel工具:可变条目数据无法写入列表框及表格

问题修复:电子表格工具数据无法写入Excel与Listbox

核心问题分析

  • Entry控件未被追踪:创建Entry和Label后,没有将它们存入self.entry_widgets列表,导致save_data方法无法获取输入的内容。
  • Excel工作簿提前关闭:在生成Entry的循环中,错误地在列数超限位置调用wb.close(),后续操作会因工作簿已关闭失效。
  • Listbox重复插入数据:每次保存时遍历整个data_list插入,导致旧数据重复显示。
  • 无效的表头清理操作:初始化阶段entry_widgets为空,调用remove_unused_headers会清空所有表头,完全没必要。

修复后的完整代码

from tkinter import *
import os.path
import openpyxl


class FlexTabApp(): 

    def __init__(self, root):
        root.title("FlexTab")
        frame = Frame(root, borderwidth=2, relief="sunken")
        frame.grid(column=1, row=1, sticky=(N, E, S, W))
        root.columnconfigure(1, weight=1)
        root.rowconfigure(1, weight=1)
        self.entry_widgets = []  # 用于存储Entry和对应的Label

        excel_file_path = r'C:\Users\BZ-eldag\Documents\Python\FlexTab\FlexTab_List.xlsx'

        if os.path.exists(excel_file_path):
            wb = openpyxl.load_workbook(excel_file_path)
            ws = wb.active
            
            row_index = 1
            row_values = []
            while True:
                row = ws[row_index]
                if not all([cell.value is None for cell in row]):
                    row_values.append([cell.value for cell in row])
                else:
                    break
                row_index += 1
            
            wb.close()

            new_excel_file_path = r'C:\Users\BZ-eldag\Documents\Python\FlexTab\FlexTab_Tabelle.xlsx'

            if os.path.exists(new_excel_file_path):
                wb = openpyxl.load_workbook(new_excel_file_path)
            else:
                wb = openpyxl.Workbook()

            ws = wb.active
            # 写入表头(原Excel首列内容作为新Excel的表头)
            for i, values in enumerate(row_values):
                for j, value in enumerate(values):
                    if value is not None:
                        value = str(value)
                    ws.cell(row=j+1, column=i+1, value=value)

            wb.save(new_excel_file_path)
            wb.close()

            wb = openpyxl.load_workbook(new_excel_file_path)
            ws = wb.active

            row_index = 2
            col_index = 1
            max_cols_per_row = 5
            row_offset = 0

            for col in ws.iter_cols():
                if col and col[0].value is not None:
                    label = col[0].value
                    
                    label_widget = Label(frame, text=label)
                    label_widget.grid(row=row_index+row_offset, column=col_index)

                    entry = Entry(frame, width=15)
                    entry.grid(row=row_index+row_offset+1, column=col_index)

                    # 将Label和Entry存入列表,方便后续获取数据
                    self.entry_widgets.append({"label": label_widget, "entry": entry})

                    col_index += 1
                    if col_index > max_cols_per_row:
                        col_index = 1
                        row_offset += 2
            # 循环结束后再关闭工作簿
            wb.close()

        else:
            print(f'Die Datei {excel_file_path} existiert nicht.')

        self.data_list = []

        self.data_listbox = Listbox(frame)
        self.data_listbox.grid(row=row_index+row_offset+3, column=1, columnspan=max_cols_per_row*2)

        save_button = Button(frame, text="Speichern", command=self.save_data)
        save_button.grid(row=row_index+row_offset+2, column=1)

    def save_data(self):
        # 获取当前所有Entry的输入值
        current_data = [widget["entry"].get() for widget in self.entry_widgets]
        self.data_list.append(current_data)
        # 只插入新的一组数据,避免重复
        self.data_listbox.insert(END, current_data)

        new_excel_file_path = r'C:\Users\BZ-eldag\Documents\Python\FlexTab\FlexTab_Tabelle.xlsx'
        wb = openpyxl.load_workbook(new_excel_file_path)
        ws = wb.active
        
        # 获取当前最后一行,用于写入新数据
        last_row = ws.max_row + 1
        # 写入对应列的数据
        for i, widget in enumerate(self.entry_widgets):
            value = widget["entry"].get()
            ws.cell(row=last_row, column=i+1, value=value)
        
        wb.save(new_excel_file_path)
        wb.close()

    def remove_unused_headers(self, used_headers):
        new_excel_file_path = r'C:\Users\BZ-eldag\Documents\Python\FlexTab\FlexTab_Tabelle.xlsx'

        wb = openpyxl.load_workbook(new_excel_file_path)
        ws = wb.active

        col_index = 1
        while True:
            if ws.cell(row=1, column=col_index).value is None:
                break

            header = str(ws.cell(row=1, column=col_index).value)
            if header not in used_headers:
                ws.delete_cols(col_index)
            else:
                col_index += 1

        wb.save(new_excel_file_path)
        wb.close()
        

root = Tk()
FlexTabApp(root)
root.mainloop()

关键修复点说明

  1. 追踪Entry控件:创建Entry和Label后,将它们以字典形式存入self.entry_widgets,方便save_data方法获取输入值和表头文本。
  2. 修正工作簿关闭时机:将wb.close()移到生成Entry的循环结束后,避免提前关闭导致后续操作失败。
  3. 避免Listbox重复插入:只将当前新增的一组数据插入Listbox,而不是遍历整个列表重复插入。
  4. 移除无效初始化操作:删除初始化阶段调用的remove_unused_headers,此时还没有用户输入,该操作完全无效。

内容的提问来源于stack exchange,提问作者Argorock89

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 06:47:14