如何用Openpyxl结合Tkinter实现Excel工作表密码锁定
问题说明
我想用Python的Openpyxl库实现Excel工作表保护,开发一个数据录入界面,需求如下:
- 普通用户:能通过界面录入数据、查看Excel内容,但无法手动修改Excel文件
- 管理员:可凭密码修改Excel中的信息
但多次尝试保护工作表都没成功,下面是我的原代码和错误的实现代码,求正确方案。
原代码(无保护逻辑)
import os import openpyxl import tkinter from tkinter import ttk def enter_data(): nombre = first_name_entry.get() apellido = last_name_entry.get() print("Nombre: ", nombre, "Apellido: ", apellido) filepath= "C:/Users/franc/Documents/Python/Prueba con excel/Viaticos.xlsx" if not os.path.exists(filepath): workbook = openpyxl.Workbook() sheet = workbook.active heading = ["Nombre", "Apellido"] sheet.append(heading) workbook.save(filepath) workbook = openpyxl.load_workbook(filepath) sheet = workbook.active sheet.append([nombre, apellido]) workbook.save(filepath) window = tkinter.Tk() window.title('Viaticos Neutics') frame = tkinter.Frame(window) frame.pack() user_info_frame = tkinter.LabelFrame(frame, text="Informacion Personal") user_info_frame.grid(row= 0, column=0, padx=20, pady=20) # Name and last name first_name_label = tkinter.Label(user_info_frame, text="Nombre") first_name_label.grid(row=0, column=0) last_name_label = tkinter.Label(user_info_frame, text = "Apellido") last_name_label.grid(row=0, column=1) # Name and lastname entry first_name_entry = tkinter.Entry(user_info_frame) first_name_entry.grid(row=1, column=0) last_name_entry = tkinter.Entry(user_info_frame) last_name_entry.grid(row=1, column=1) window.mainloop()
错误的保护实现代码
import os import openpyxl import tkinter from tkinter import ttk def enter_data(): nombre = first_name_entry.get() apellido = last_name_entry.get() print("Nombre: ", nombre, "Apellido: ", apellido) filepath= "C:/Users/franc/Documents/Python/Prueba con excel/Viaticos.xlsx" # set a password password = "123" # unprotect the sheet sheet.unprotect.password workbook = openpyxl.load_workbook(filepath) sheet = workbook.active # protect the sheet before save sheet.protect.password sheet.append([nombre, apellido]) workbook.save(filepath) window = tkinter.Tk() window.title('Viaticos Neutics') frame = tkinter.Frame(window) frame.pack() user_info_frame = tkinter.LabelFrame(frame, text="Informacion Personal") user_info_frame.grid(row= 0, column=0, padx=20, pady=20) # Name and last name first_name_label = tkinter.Label(user_info_frame, text="Nombre") first_name_label.grid(row=0, column=0) last_name_label = tkinter.Label(user_info_frame, text = "Apellido") last_name_label.grid(row=0, column=1) # Name and lastname entry first_name_entry = tkinter.Entry(user_info_frame) first_name_entry.grid(row=1, column=0) last_name_entry = tkinter.Entry(user_info_frame) last_name_entry.grid(row=1, column=1) window.mainloop()
错误点分析
- 调用顺序错误:在加载工作簿(
openpyxl.load_workbook)之前就尝试操作sheet对象,此时sheet还未定义,会直接报错。 - 保护方法使用错误:Openpyxl中,工作表的保护/解除保护是通过方法调用实现的:
- 解除保护:
sheet.unprotect(password)(需传入密码参数) - 保护工作表:
sheet.protect(password)(需传入密码参数)
错误代码中直接访问sheet.protect.password是无效的,不属于正确调用方式。
- 解除保护:
正确实现方案
我们需要实现两个核心逻辑:
- 新建Excel文件时直接设置保护密码,防止手动修改
- 普通用户录入数据时,程序自动完成「解除保护→追加数据→重新保护」的流程;管理员需验证密码后才能进行修改操作
以下是完整代码:
import os import openpyxl import tkinter from tkinter import messagebox ADMIN_PASSWORD = "123" FILEPATH = "C:/Users/franc/Documents/Python/Prueba con excel/Viaticos.xlsx" def enter_data(): nombre = first_name_entry.get().strip() apellido = last_name_entry.get().strip() if not nombre or not apellido: messagebox.showerror("错误", "请填写完整信息") return print(f"Nombre: {nombre}, Apellido: {apellido}") # 处理Excel文件 try: if not os.path.exists(FILEPATH): # 新建文件时直接设置保护,允许选中单元格查看内容 workbook = openpyxl.Workbook() sheet = workbook.active sheet.append(["Nombre", "Apellido"]) sheet.protect(password=ADMIN_PASSWORD, selectCells=True) workbook.save(FILEPATH) else: # 加载现有文件,解除保护后追加数据 workbook = openpyxl.load_workbook(FILEPATH) sheet = workbook.active sheet.unprotect(password=ADMIN_PASSWORD) sheet.append([nombre, apellido]) # 重新保护工作表 sheet.protect(password=ADMIN_PASSWORD, selectCells=True) workbook.save(FILEPATH) messagebox.showinfo("成功", "数据已录入") # 清空输入框 first_name_entry.delete(0, tkinter.END) last_name_entry.delete(0, tkinter.END) except Exception as e: messagebox.showerror("错误", f"数据录入失败:{str(e)}") def admin_modify(): # 管理员密码验证窗口 password_window = tkinter.Toplevel(window) password_window.title("管理员验证") tkinter.Label(password_window, text="请输入管理员密码:").pack(pady=10) password_entry = tkinter.Entry(password_window, show="*") password_entry.pack(pady=5) def check_password(): input_pwd = password_entry.get().strip() if input_pwd == ADMIN_PASSWORD: password_window.destroy() messagebox.showinfo("成功", "验证通过,可进行修改操作") # 这里可扩展具体的修改功能,比如打开Excel文件或启动编辑界面 # os.startfile(FILEPATH) else: messagebox.showerror("错误", "密码错误") tkinter.Button(password_window, text="确认", command=check_password).pack(pady=10) password_window.grab_set() # 界面构建 window = tkinter.Tk() window.title('Viaticos Neutics') frame = tkinter.Frame(window) frame.pack(pady=20) # 用户信息录入框 user_info_frame = tkinter.LabelFrame(frame, text="Informacion Personal") user_info_frame.grid(row=0, column=0, padx=20, pady=10) # 姓名标签和输入框 first_name_label = tkinter.Label(user_info_frame, text="Nombre") first_name_label.grid(row=0, column=0, padx=5, pady=5) first_name_entry = tkinter.Entry(user_info_frame) first_name_entry.grid(row=1, column=0, padx=5, pady=5) last_name_label = tkinter.Label(user_info_frame, text="Apellido") last_name_label.grid(row=0, column=1, padx=5, pady=5) last_name_entry = tkinter.Entry(user_info_frame) last_name_entry.grid(row=1, column=1, padx=5, pady=5) # 按钮区域 button_frame = tkinter.Frame(frame) button_frame.grid(row=1, column=0, pady=10) tkinter.Button(button_frame, text="录入数据", command=enter_data).grid(row=0, column=0, padx=10) tkinter.Button(button_frame, text="管理员修改", command=admin_modify).grid(row=0, column=1, padx=10) window.mainloop()
代码说明
- 工作表保护逻辑:新建文件时通过
sheet.protect()设置保护,允许用户选中单元格查看;录入数据时自动解除保护、追加数据后再重新保护,保证文件始终处于保护状态。 - 管理员功能:添加密码验证窗口,验证通过后可进入修改流程(可根据需求扩展具体修改功能)。
- 用户体验优化:添加输入合法性校验、操作结果提示,录入后自动清空输入框。
内容的提问来源于stack exchange,提问作者franco BlackWP
相关产品推荐
相关产品推荐

