《还在手动加密解密Excel?Python批量加密解密工具来了!》
- 2026-11-02 22:55:11



“带你横跨办公自动化的数据江海”
@摸鱼
前言
关于摸鱼
(
ABOUT MOYU
)
闻道有先后,术业有专攻。
各位大佬朋友们好!
~我依旧是你们的老朋友摸鱼~
在职场摸爬滚打的这十多年里,我用Python悄悄干了不少“正事”——不知不觉攒下了一整套办公自动化的实用项目技巧。去年10月初创立了公众号 「码海听潮」 ,初衷很简单:把重复的劳动交给代码,把摸鱼的时间留给生活。
目前已经吭哧吭哧更新了100多篇原创文章,每一篇都是实操干货,不讲虚的,只聊怎么用代码真正解放双手,帮大家早点下班、准点摸鱼

《办公需求场景再现:》
有一堆凌乱的 Excel 文件,内有多个 sheet、多类敏感数据和多种使用场景。现在的需求是:对这批表格进行批量加密或解密,假如这种级别的任务,你的 Big Boss 直接甩给你来负责,请问阁下该如何挠头?
需求文件列表截图:


《办公痛点分析:》
01
痛点1:量大耗时,重复劳动极其枯燥
如果有几百上千个Excel文件,手动逐个打开 → 点击“文件” → “保护工作簿” → 输入密码 → 保存 → 关闭。这一套动作做几十遍后人就会开始烦躁,做几百遍极易出错(如忘记是否已加密)。
02
痛点2:密码管理混乱,容易遗失或泄露
各自为政: 不同人设置的密码不同(有的用“123456”,有的用生日,有的用部门缩写),后期维护灾难。
无统一规则: 需要解密时,不知道原密码是什么,只能一个个试或绕路找原设置人。
03
痛点3:多 sheet / 多场景下规则不统一,极易遗漏
同一文件内: 有些文件需要对整个工作簿加密,有些只对特定 sheet 加密,人工操作时很容易忘记勾选对应选项,导致本该加密的 sheet 暴露。
不同文件间: 财务文件用密码A,人事文件用密码B,周报文件不加密。人工筛选时,极易把财务文件当周报漏加密,或把不加密的周报也加了密。

《办公需求解决思路:》
1.获取任务列表:扫描出该文件夹下递归所有Excel文件(.xls, .xlsx 等)。
2.逐个处理文件:遍历文件列表,对每个文件执行加密:

《办公代码展示:》
下面,我就用python代码让各位大佬见识一下,什么叫"传统文化遇上赛博效率"
import sysfrom pathlib import Pathfrom PyQt6.QtWidgets import (QApplication, QMainWindow, QWidget, QVBoxLayout, QHBoxLayout,QLabel, QLineEdit, QPushButton, QFileDialog, QMessageBox,QGroupBox, QRadioButton, QCheckBox,QStatusBar, QButtonGroup, QSplitter, QTextEdit)from PyQt6.QtCore import Qt, QSettingsfrom PyQt6.QtGui import QFont, QTextCursorclass ExcelPasswordTool(QMainWindow):def __init__(self):super().__init__()self.setWindowTitle("Excel批量加密解密工具(欢迎关注微信公众号:码海听潮)")self.setFixedSize(780, 580)# 设置应用样式self.setup_style()# 主窗口部件central_widget = QWidget()self.setCentralWidget(central_widget)main_layout = QHBoxLayout(central_widget)main_layout.setSpacing(10)main_layout.setContentsMargins(10, 10, 10, 10)# 创建分割器splitter = QSplitter(Qt.Orientation.Horizontal)main_layout.addWidget(splitter)# 左侧面板(30%)left_panel = QWidget()left_panel.setMinimumWidth(300)left_layout = QVBoxLayout(left_panel)left_layout.setSpacing(15)left_layout.setContentsMargins(0, 0, 0, 0)# 右侧日志面板(70%)right_panel = QWidget()right_layout = QVBoxLayout(right_panel)right_layout.setContentsMargins(0, 0, 0, 0)# 创建日志文本框log_group = QGroupBox("执行日志")log_layout = QVBoxLayout(log_group)log_layout.setContentsMargins(10, 15, 10, 10)self.log_text = QTextEdit()self.log_text.setReadOnly(True)self.log_text.setPlaceholderText("日志将显示在这里...")self.log_text.setStyleSheet("""QTextEdit {font-family: 'Consolas', 'Microsoft YaHei';font-size: 11px;border: 1px solid#E0E0E0;border-radius: 5px;background-color:#FAFAFA;}""")log_layout.addWidget(self.log_text)# 添加清空日志按钮clear_log_btn = QPushButton("清空日志")clear_log_btn.setObjectName("secondary")clear_log_btn.clicked.connect(self.clear_log)log_layout.addWidget(clear_log_btn)right_layout.addWidget(log_group)# 将面板添加到分割器splitter.addWidget(left_panel)splitter.addWidget(right_panel)splitter.setSizes([300, 700])# 设置加密和解密功能在左侧面板self.setup_encrypt_section(left_layout)self.setup_decrypt_section(left_layout)# 添加弹性空间left_layout.addStretch()# 状态栏self.status_bar = QStatusBar()self.setStatusBar(self.status_bar)self.status_bar.showMessage("准备就绪")self.status_bar.setStyleSheet("""QStatusBar {background-color:#F5F5F5;padding: 5px;font-size: 11px;color:#666;}""")# 加载设置self.load_settings()def setup_style(self):"""设置应用样式"""self.setStyleSheet("""QMainWindow {background-color:#F8F9FA;}QLabel {color:#333;}QGroupBox {font-weight: bold;border: 1px solid#E0E0E0;border-radius: 8px;margin-top: 12px;padding-top: 10px;background-color: white;}QGroupBox::title {subcontrol-origin: margin;left: 10px;padding: 0 5px;color:#0078d7;}QLineEdit {border: 1px solid#D0D0D0;border-radius: 5px;padding: 8px;background-color: white;font-size: 12px;}QLineEdit:focus {border-color:#0078d7;outline: none;}QPushButton {border: none;border-radius: 5px;padding: 8px 16px;font-weight: bold;font-size: 12px;}QPushButton#primary{background-color:#0078d7;color: white;}QPushButton#primary:hover {background-color:#005a9e;}QPushButton#primary:pressed {background-color:#004578;}QPushButton#danger{background-color:#d83b01;color: white;}QPushButton#danger:hover {background-color:#b52a00;}QPushButton#secondary{background-color:#f0f0f0;color:#333;border: 1px solid#D0D0D0;}QPushButton#secondary:hover {background-color:#e5e5e5;}QRadioButton {spacing: 8px;font-size: 12px;}QCheckBox {spacing: 8px;font-size: 12px;}""")def setup_encrypt_section(self, parent_layout):"""设置加密功能区域"""encrypt_group = QGroupBox("加密Excel")encrypt_layout = QVBoxLayout(encrypt_group)encrypt_layout.setSpacing(10)encrypt_layout.setContentsMargins(15, 15, 15, 15)# 文件夹选择folder_layout = QHBoxLayout()self.folder_path = QLineEdit()self.folder_path.setPlaceholderText("请选择文件夹...")folder_layout.addWidget(self.folder_path)browse_btn = QPushButton("浏览")browse_btn.setObjectName("secondary")browse_btn.clicked.connect(self.browse_folder)folder_layout.addWidget(browse_btn)encrypt_layout.addLayout(folder_layout)# 密码输入pwd_layout = QHBoxLayout()pwd_label = QLabel("密码:")pwd_label.setMinimumWidth(40)pwd_layout.addWidget(pwd_label)self.password_entry = QLineEdit()self.password_entry.setEchoMode(QLineEdit.EchoMode.Password)pwd_layout.addWidget(self.password_entry)encrypt_layout.addLayout(pwd_layout)# 确认密码confirm_layout = QHBoxLayout()confirm_label = QLabel("确认:")confirm_label.setMinimumWidth(40)confirm_layout.addWidget(confirm_label)self.confirm_entry = QLineEdit()self.confirm_entry.setEchoMode(QLineEdit.EchoMode.Password)confirm_layout.addWidget(self.confirm_entry)encrypt_layout.addLayout(confirm_layout)# 记住密码self.save_password_check = QCheckBox("记住密码")self.save_password_check.toggled.connect(self.toggle_save_password)encrypt_layout.addWidget(self.save_password_check)# 加密按钮self.encrypt_btn = QPushButton("开始加密")self.encrypt_btn.setObjectName("primary")self.encrypt_btn.clicked.connect(self.protect_files)encrypt_layout.addWidget(self.encrypt_btn)# 清除设置按钮clear_encrypt_btn = QPushButton("清除设置")clear_encrypt_btn.setObjectName("secondary")clear_encrypt_btn.clicked.connect(self.clear_encrypt_settings)encrypt_layout.addWidget(clear_encrypt_btn)parent_layout.addWidget(encrypt_group)def setup_decrypt_section(self, parent_layout):"""设置解密功能区域"""decrypt_group = QGroupBox("解密Excel")decrypt_layout = QVBoxLayout(decrypt_group)decrypt_layout.setSpacing(10)decrypt_layout.setContentsMargins(15, 15, 15, 15)# 文件选择file_layout = QHBoxLayout()self.file_path = QLineEdit()self.file_path.setPlaceholderText("请选择Excel文件...")file_layout.addWidget(self.file_path)browse_btn = QPushButton("浏览")browse_btn.setObjectName("secondary")browse_btn.clicked.connect(self.browse_file)file_layout.addWidget(browse_btn)decrypt_layout.addLayout(file_layout)# 解密方法self.method_vba = QRadioButton("自动破解(推荐)")self.method_vba.setChecked(True)self.method_known = QRadioButton("已知密码移除")decrypt_layout.addWidget(self.method_vba)decrypt_layout.addWidget(self.method_known)# 已知密码输入self.known_pass_frame = QWidget()known_layout = QHBoxLayout(self.known_pass_frame)known_layout.setContentsMargins(20, 0, 0, 0)known_label = QLabel("已知密码:")known_label.setMinimumWidth(70)known_layout.addWidget(known_label)self.known_pass_entry = QLineEdit()self.known_pass_entry.setEchoMode(QLineEdit.EchoMode.Password)known_layout.addWidget(self.known_pass_entry)decrypt_layout.addWidget(self.known_pass_frame)self.known_pass_frame.setVisible(False)# 绑定方法选择事件self.method_vba.toggled.connect(self.on_method_change)self.method_known.toggled.connect(self.on_method_change)# 解密按钮self.decrypt_btn = QPushButton("开始解密")self.decrypt_btn.setObjectName("danger")self.decrypt_btn.clicked.connect(self.start_decrypt)decrypt_layout.addWidget(self.decrypt_btn)# 清除选择按钮clear_decrypt_btn = QPushButton("清除选择")clear_decrypt_btn.setObjectName("secondary")clear_decrypt_btn.clicked.connect(self.clear_decrypt_settings)decrypt_layout.addWidget(clear_decrypt_btn)parent_layout.addWidget(decrypt_group)# ========== 槽函数(空实现) ==========def browse_folder(self):"""浏览文件夹"""folder = QFileDialog.getExistingDirectory(self, "选择文件夹")if folder:self.folder_path.setText(folder)self.add_log(f"已选择文件夹: {folder}")def browse_file(self):"""浏览文件"""file_path, _ = QFileDialog.getOpenFileName(self, "选择Excel文件", "", "Excel文件 (*.xls *.xlsx)")if file_path:self.file_path.setText(file_path)self.add_log(f"已选择文件: {file_path}")def on_method_change(self):"""解密方法选择变化"""self.known_pass_frame.setVisible(self.method_known.isChecked())def protect_files(self):"""加密文件(空实现)"""folder_path = self.folder_path.text()password = self.password_entry.text()confirm = self.confirm_entry.text()if not folder_path:QMessageBox.critical(self, "错误", "请选择文件夹路径")returnif not password:QMessageBox.critical(self, "错误", "请输入密码")returnif password != confirm:QMessageBox.critical(self, "错误", "两次输入的密码不一致")returnif not Path(folder_path).exists():QMessageBox.critical(self, "错误", "指定的文件夹不存在")returnself.add_log(f"开始加密文件夹: {folder_path}")# 此处可添加加密逻辑def start_decrypt(self):"""开始解密(空实现)"""file_path = self.file_path.text()if not file_path:QMessageBox.critical(self, "错误", "请选择Excel文件")returnif not Path(file_path).exists():QMessageBox.critical(self, "错误", "指定的文件不存在")returnmethod = self.method_vba.isChecked()if not method:password = self.known_pass_entry.text()if not password:QMessageBox.critical(self, "错误", "请输入已知密码")returnmethod_name = "VBA自动破解" if method else "已知密码移除"self.add_log(f"开始解密文件: {file_path}")self.add_log(f"解密方法: {method_name}")# 此处可添加解密逻辑def add_log(self, message):"""添加日志到日志文本框"""from datetime import datetimetimestamp = datetime.now().strftime("%H:%M:%S")formatted_message = f"[{timestamp}] {message}"self.log_text.append(formatted_message)cursor = self.log_text.textCursor()cursor.movePosition(QTextCursor.MoveOperation.End)self.log_text.setTextCursor(cursor)def clear_log(self):"""清空日志"""self.log_text.clear()self.add_log("日志已清空")def save_settings(self, password):"""保存设置"""settings = QSettings("ExcelTool", "Settings")settings.setValue("folder_path", self.folder_path.text())settings.setValue("password", password)settings.setValue("save_password", self.save_password_check.isChecked())def load_settings(self):"""加载设置"""settings = QSettings("ExcelTool", "Settings")folder_path = settings.value("folder_path", "")save_password = settings.value("save_password", False, type=bool)if folder_path:self.folder_path.setText(folder_path)if save_password:password = settings.value("password", "")if password:self.password_entry.setText(password)self.confirm_entry.setText(password)self.save_password_check.setChecked(True)def clear_saved_password(self):"""清除保存的密码"""settings = QSettings("ExcelTool", "Settings")settings.setValue("password", "")settings.setValue("save_password", False)def toggle_save_password(self, checked):"""切换是否保存密码"""if not checked:self.clear_saved_password()def clear_encrypt_settings(self):"""清除加密设置"""self.folder_path.clear()self.password_entry.clear()self.confirm_entry.clear()self.save_password_check.setChecked(False)self.status_bar.showMessage("加密设置已清除")self.add_log("加密设置已清除")def clear_decrypt_settings(self):"""清除解密设置"""self.file_path.clear()self.known_pass_entry.clear()self.method_vba.setChecked(True)self.status_bar.showMessage("解密设置已清除")self.add_log("解密设置已清除")def main():app = QApplication(sys.argv)font = QFont("Microsoft YaHei", 9)app.setFont(font)window = ExcelPasswordTool()window.show()sys.exit(app.exec())if __name__ == "__main__":main()
最终对所有excel进行了加密解密,完美实现了之前既定的需求.......


通过上面Python自动化脚本,仅用几秒钟的时间就完成原需手动操作数小时甚至数天的工作任务。从最初准备手动人工机械操作的麻木到用python实现高效自动化的畅快,工作效率获得指数级提升,终于实现了不加班熬夜的自由!
大佬们也可以举一反三,参照上面的代码思路根据自己工作中的实际情况来具体问题具体分析,实现自己定制化的需求。
结语
当Python遇见办公,牛马打工人终于笑出了猪叫声
【职场人必看】每天早上一睁眼,想到又要面对:
1.📊 堆积如山的Excel表格
2.📑 机械重复的复制粘贴
3.✍️ 永远改不完的各类文档
4.诸如此类的更多........
是不是连Ctrl+Alt+Delete的心都有了?
别慌!别急,摸鱼这位“职场外挂”已经带着Python代码来拯救你了!
友情提示:考虑到没有python环境的朋友需要打包好的成品exe,摸鱼早已贴心打包好,本篇文章代码打包的exe截图如下:

感谢各位大佬观看,还望各位大佬抬抬贵手一键三连,多多关注点赞转发评论,大佬们的支持才是摸鱼孜孜不倦更新原创干货的动力!