import sysimport osfrom datetime import datetimefrom PyQt6.QtWidgets import ( QApplication, QMainWindow, QWidget, QVBoxLayout, QHBoxLayout, QPushButton, QTextEdit, QLabel, QFileDialog, QGroupBox, QMessageBox)from PyQt6.QtCore import Qt, QThread, pyqtSignalfrom PyQt6.QtGui import QTextCursor, QColorclass ExtractionThread(QThread): """提取线程基类,实际使用时需要继承并实现具体逻辑""" log_message = pyqtSignal(str) extraction_finished = pyqtSignal(int, int) def __init__(self, folder_path): super().__init__() self.folder_path = folder_path self.is_running = True def stop(self): self.is_running = False def run(self): # 这是一个示例实现,实际使用时需要替换为真正的提取逻辑 self.log_message.emit(f"开始处理文件夹: {self.folder_path}") # 模拟处理过程 import time for i in range(10): if not self.is_running: break time.sleep(0.5) self.log_message.emit(f"处理进度: {i+1}/10") self.extraction_finished.emit(5, 10)class MainWindow(QMainWindow): def __init__(self): super().__init__() self.worker_thread = None self.init_ui() def append_log(self, text, color=None): """添加日志到文本框""" cursor = self.log_text.textCursor() cursor.movePosition(QTextCursor.MoveOperation.End) # 设置颜色 if color: self.log_text.setTextColor(QColor(color)) else: # 根据内容自动判断颜色 if "✓" in text or "成功" in text or "保存成功" in text: self.log_text.setTextColor(QColor("#4CAF50")) # 绿色 elif "✗" in text or "失败" in text or "错误" in text or "出错" in text: self.log_text.setTextColor(QColor("#F44336")) # 红色 elif "⚠" in text or "警告" in text: self.log_text.setTextColor(QColor("#FF9800")) # 橙色 elif "===" in text or "###" in text or "处理文件" in text or "开始处理" in text: self.log_text.setTextColor(QColor("#2196F3")) # 蓝色 elif "生成表格" in text or "创建文件夹" in text: self.log_text.setTextColor(QColor("#9C27B0")) # 紫色 else: self.log_text.setTextColor(QColor("#333333")) # 深灰色 self.log_text.setTextCursor(cursor) self.log_text.insertPlainText(text + "\n") self.log_text.ensureCursorVisible() def init_ui(self): self.setWindowTitle("Word表格批量提取工具(欢迎关注微信公众号:码海听潮)") self.setGeometry(100, 100, 700, 600) # 设置应用样式 self.setStyleSheet(""" QMainWindow { background-color: #f5f5f5; } QGroupBox { font-weight: bold; border: 2px solid #cccccc; border-radius: 8px; margin-top: 1ex; padding-top: 10px; background-color: white; } QGroupBox::title { subcontrol-origin: margin; left: 10px; padding: 0 5px 0 5px; color: #2196F3; } QPushButton { background-color: #2196F3; color: white; border: none; border-radius: 5px; padding: 8px 16px; font-weight: bold; min-width: 100px; } QPushButton:hover { background-color: #1976D2; } QPushButton:pressed { background-color: #0D47A1; } QPushButton:disabled { background-color: #BDBDBD; } QPushButton#stopButton { background-color: #F44336; } QPushButton#stopButton:hover { background-color: #D32F2F; } QLabel { color: #333333; } QTextEdit { border: 1px solid #cccccc; border-radius: 5px; background-color: #fafafa; font-family: 'Consolas', 'Courier New', monospace; font-size: 12px; line-height: 1.5; } """) # 创建中央部件 central_widget = QWidget() self.setCentralWidget(central_widget) main_layout = QVBoxLayout(central_widget) main_layout.setSpacing(15) main_layout.setContentsMargins(20, 20, 20, 20) # 文件夹选择区域 folder_group = QGroupBox("📁 文件夹设置") folder_layout = QVBoxLayout(folder_group) path_layout = QHBoxLayout() self.folder_path_label = QLabel("未选择文件夹") self.folder_path_label.setStyleSheet(""" background-color: #FFF3E0; border: 1px solid #FFB74D; border-radius: 3px; padding: 8px; color: #E65100; """) self.folder_path_label.setWordWrap(True) path_layout.addWidget(self.folder_path_label, 1) self.browse_button = QPushButton("📂 选择文件夹") self.browse_button.clicked.connect(self.browse_folder) path_layout.addWidget(self.browse_button) folder_layout.addLayout(path_layout) main_layout.addWidget(folder_group) # 日志显示区域 log_group = QGroupBox("📝 处理日志") log_layout = QVBoxLayout(log_group) self.log_text = QTextEdit() self.log_text.setReadOnly(True) log_layout.addWidget(self.log_text) main_layout.addWidget(log_group, 1) # 按钮区域 button_layout = QHBoxLayout() self.start_button = QPushButton("▶ 开始提取") self.start_button.clicked.connect(self.start_extraction) self.start_button.setMinimumHeight(40) button_layout.addWidget(self.start_button) self.stop_button = QPushButton("⏹ 停止") self.stop_button.setObjectName("stopButton") self.stop_button.clicked.connect(self.stop_extraction) self.stop_button.setEnabled(False) self.stop_button.setMinimumHeight(40) button_layout.addWidget(self.stop_button) self.clear_button = QPushButton("🗑 清空日志") self.clear_button.clicked.connect(self.clear_log) self.clear_button.setStyleSheet(""" QPushButton { background-color: #607D8B; } QPushButton:hover { background-color: #455A64; } """) self.clear_button.setMinimumHeight(40) button_layout.addWidget(self.clear_button) main_layout.addLayout(button_layout) # 显示启动信息 self.append_log("📌 功能说明:") self.append_log(" 1. 自动识别以'表'开头的表格标题(如:表1、表2-1等)") self.append_log(" 2. 将标题和表格一起提取并保存为独立的Word文档") def browse_folder(self): folder_path = QFileDialog.getExistingDirectory( self, "选择包含Word文档的文件夹", os.path.expanduser("~"), QFileDialog.Option.ShowDirsOnly ) if folder_path: self.folder_path_label.setText(folder_path) self.folder_path_label.setStyleSheet(""" background-color: #E8F5E9; border: 1px solid #81C784; border-radius: 3px; padding: 8px; color: #2E7D32; """) self.append_log(f"\n✅ 已选择文件夹: {folder_path}") # 扫描并显示文件夹内容 word_extensions = ['.docx', '.doc'] word_files = [] for root, dirs, files in os.walk(folder_path): for file in files: if any(file.lower().endswith(ext) for ext in word_extensions): if not file.startswith('~$'): word_files.append(os.path.join(root, file)) if word_files: self.append_log(f"📊 发现 {len(word_files)} 个Word文档") self.append_log("📄 文档列表:") for i, file in enumerate(word_files[:10], 1): rel_path = os.path.relpath(file, folder_path) self.append_log(f" {i}. {rel_path}") if len(word_files) > 10: self.append_log(f" ... 还有 {len(word_files) - 10} 个文档") self.append_log("") else: self.append_log("⚠ 该文件夹中没有找到Word文档") self.append_log("") def start_extraction(self): folder_path = self.folder_path_label.text() if folder_path == "未选择文件夹": QMessageBox.warning(self, "警告", "请先选择文件夹!") return if not os.path.exists(folder_path): QMessageBox.critical(self, "错误", "选择的文件夹不存在!") return # 确认开始处理 reply = QMessageBox.question( self, "确认", "开始提取表格?\n\n" "注意:\n" "1. 处理过程中会打开Word应用\n" "2. 请确保Word文档未被其他程序占用\n" "3. 提取的表格将保存在原文档所在目录\n" "4. 默认包含子文件夹,标题查找范围为5段", QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No ) if reply != QMessageBox.StandardButton.Yes: return # 清空日志 self.log_text.clear() # 更新UI状态 self.start_button.setEnabled(False) self.stop_button.setEnabled(True) self.browse_button.setEnabled(False) # 创建并启动工作线程 # 注意:这里需要使用实际的提取线程类替换ExtractionThread self.worker_thread = ExtractionThread(folder_path) self.worker_thread.extraction_finished.connect(self.on_extraction_finished) self.worker_thread.log_message.connect(self.on_log_message) self.worker_thread.start() self.append_log(f"\n{'='*80}") self.append_log(f"🚀 开始处理任务") self.append_log(f"📁 目标文件夹: {folder_path}") self.append_log(f"{'='*80}\n") def stop_extraction(self): if self.worker_thread and self.worker_thread.isRunning(): reply = QMessageBox.question( self, "确认停止", "确定要停止处理吗?\n已处理的文件将保留。", QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No ) if reply == QMessageBox.StandardButton.Yes: self.worker_thread.stop() self.stop_button.setEnabled(False) self.append_log("\n⏸ 用户已请求停止处理...") def on_extraction_finished(self, success_count, total_files): self.start_button.setEnabled(True) self.stop_button.setEnabled(False) self.browse_button.setEnabled(True) # 显示完成消息 if total_files > 0: QMessageBox.information( self, "处理完成", f"表格提取完成!\n\n" f"处理文件数: {total_files}\n" f"提取表格数: {success_count}" ) def on_log_message(self, message): """接收线程发送的日志消息""" # 添加时间戳 timestamp = datetime.now().strftime('%H:%M:%S') formatted_message = f"[{timestamp}] {message}" self.append_log(formatted_message) def clear_log(self): self.log_text.clear() self.append_log("🗑 日志已清空") self.append_log("") def closeEvent(self, event): if self.worker_thread and self.worker_thread.isRunning(): reply = QMessageBox.question( self, "确认退出", "处理正在进行中,确定要退出吗?", QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No ) if reply == QMessageBox.StandardButton.Yes: self.worker_thread.stop() self.worker_thread.wait(3000) event.accept() else: event.ignore() else: event.accept()if __name__ == "__main__": app = QApplication(sys.argv) app.setStyle('Fusion') window = MainWindow() window.show() sys.exit(app.exec())
通过上面Python自动化脚本,仅用几秒钟的时间就完成原需手动操作数小时甚至数天的工作任务。从最初准备手动人工机械操作的麻木到用python实现高效自动化的畅快,工作效率获得指数级提升,终于实现了不加班熬夜的自由!
大佬们也可以举一反三,参照上面的代码思路根据自己工作中的实际情况来具体问题具体分析,实现自己定制化的需求。
这套工具特别适合:
工程word文档管理
科研报告表格提取
法律文书表格整理
任何需要从Word文档中批量提取表格的场景
当Python遇见办公,牛马打工人终于笑出了猪叫声
【职场人必看】每天早上一睁眼,想到又要面对:
1.📊 堆积如山的Excel表格
2.📑 机械重复的复制粘贴
3.✍️ 永远改不完的各类文档
4.诸如此类的更多........
是不是连Ctrl+Alt+Delete的心都有了?
别慌!别急,摸鱼这位“职场外挂”已经带着Python代码来拯救你了!
另外,此工具已上传绿联nas私有云,有需要的大佬私信摸鱼君获取!
感谢各位大佬观看,还望各位大佬抬抬贵手一键三连,多多关注点赞转发评论,大佬们的支持才是摸鱼孜孜不倦更新原创干货的动力!