基于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()
关键修复点说明
- 追踪Entry控件:创建Entry和Label后,将它们以字典形式存入
self.entry_widgets,方便save_data方法获取输入值和表头文本。 - 修正工作簿关闭时机:将
wb.close()移到生成Entry的循环结束后,避免提前关闭导致后续操作失败。 - 避免Listbox重复插入:只将当前新增的一组数据插入Listbox,而不是遍历整个列表重复插入。
- 移除无效初始化操作:删除初始化阶段调用的
remove_unused_headers,此时还没有用户输入,该操作完全无效。
内容的提问来源于stack exchange,提问作者Argorock89
相关产品推荐
相关产品推荐

