Office轉PDF轉換器v1.0.py

軟件介紹

這是批量將word、Excel、PPT轉換為PDF格式的軟件,不過PPT轉換為PDF需要電腦安裝了office,目前這個我還沒有解決沒有office也可以安裝的方法。

在這里插入圖片描述

軟件使用

軟件使用是比較簡單的,導入文件/文件夾,在自定義輸出路徑
在這里插入圖片描述
點擊這里的【分析文件】
在這里插入圖片描述
然后就可以轉換了
在這里插入圖片描述
轉換完成
在這里插入圖片描述

軟件源碼

我吧軟件源碼也一起放在這里了,如果有大佬可以解決不安裝office也可以將PPT轉換為PDF的話歡迎在評論區留下你的代碼
當然,為了防止小白不懂怎么打包,我也將成品放在文末了。

import os
import sys
import gc
import time
import pythoncom
import win32com.client
from PyQt5.QtWidgets import (QApplication, QMainWindow, QPushButton, QLabel, QLineEdit, QTextEdit, QVBoxLayout, QHBoxLayout, QWidget, QFileDialog, QProgressBar, QMessageBox,QGroupBox, QFormLayout, QListWidget,QListWidgetItem, QMenu, QAction)
from PyQt5.QtCore import Qt, QThread, pyqtSignal, QObject
from PyQt5.QtGui import QFont, QColorclass ConversionWorker(QObject):"""轉換工作線程,負責后臺執行轉換任務"""progress_updated = pyqtSignal(int, str)  # 進度更新信號 (進度值, 狀態文本)conversion_finished = pyqtSignal(str)    # 轉換完成信號 (完成消息)log_message = pyqtSignal(str)            # 日志消息信號def __init__(self, file_items, output_path):super().__init__()self.file_items = file_items  # 包含路徑和文件名的字典列表self.output_path = output_pathself.is_running = Truedef stop(self):"""停止轉換任務"""self.is_running = Falsedef run(self):"""執行轉換任務"""try:# 初始化COM組件pythoncom.CoInitialize()# 確保PDF文件夾存在pdf_folder = self.output_pathif not os.path.exists(pdf_folder):os.makedirs(pdf_folder)self.log_message.emit(f"已創建PDF文件夾: {pdf_folder}")# 分類文件words = []excels = []ppts = []for item in self.file_items:file_path = item['path']filename = item['name']lower_filename = filename.lower()if lower_filename.endswith(('.doc', '.docx')):words.append({"path": file_path, "name": filename})elif lower_filename.endswith(('.xls', '.xlsx')):excels.append({"path": file_path, "name": filename})elif lower_filename.endswith(('.ppt', '.pptx')):ppts.append({"path": file_path, "name": filename})total_files = len(words) + len(excels) + len(ppts)processed_files = 0# 初始化轉換統計變量word_success, word_failed = 0, 0excel_success, excel_failed = 0, 0ppt_success, ppt_failed = 0, 0# 轉換Word文件if words and self.is_running:self.log_message.emit("\n【開始 Word -> PDF 轉換】")word_success, word_failed = self.convert_words(words)processed_files += len(words)progress = int((processed_files / total_files) * 100) if total_files > 0 else 100self.progress_updated.emit(progress, f"已完成Word轉換: {word_success}成功, {word_failed}失敗")# 轉換Excel文件if excels and self.is_running:self.log_message.emit("\n【開始 Excel -> PDF 轉換】")excel_success, excel_failed = self.convert_excels(excels)processed_files += len(excels)progress = int((processed_files / total_files) * 100) if total_files > 0 else 100self.progress_updated.emit(progress, f"已完成Excel轉換: {excel_success}成功, {excel_failed}失敗")# 轉換PPT文件if ppts and self.is_running:self.log_message.emit("\n【開始 PPT -> PDF 轉換】")ppt_success, ppt_failed = self.convert_ppts(ppts)processed_files += len(ppts)progress = int((processed_files / total_files) * 100) if total_files > 0 else 100self.progress_updated.emit(progress, f"已完成PPT轉換: {ppt_success}成功, {ppt_failed}失敗")if self.is_running:total_success = word_success + excel_success + ppt_successtotal_failed = word_failed + excel_failed + ppt_failedself.conversion_finished.emit(f"轉換完成!\n總計: {total_files}個文件\n成功: {total_success}個\n失敗: {total_failed}個\nPDF文件保存位置: {self.output_path}")else:self.conversion_finished.emit("轉換已取消")except Exception as e:self.log_message.emit(f"轉換過程出錯: {str(e)}")self.conversion_finished.emit(f"轉換出錯: {str(e)}")finally:# 釋放COM組件pythoncom.CoUninitialize()gc.collect()def convert_words(self, words):"""轉換Word文件為PDF"""success = 0failed = 0word = Nonedoc = Nonetry:self.log_message.emit("打開Word進程...")word = win32com.client.Dispatch("Word.Application")word.Visible = 0word.DisplayAlerts = Falsefor i, item in enumerate(words):if not self.is_running:breakfilename = item["name"]file_path = item["path"]self.log_message.emit(f"正在轉換: {filename} ({i+1}/{len(words)})")from_file = os.path.join(file_path, filename)to_filename = self.change_suffix_to_pdf(filename)to_file = self.to_file_join(self.output_path, to_filename)try:doc = word.Documents.Open(from_file)doc.SaveAs(to_file, 17)  # 17 表示PDF格式self.log_message.emit(f"轉換完成: {to_filename}")success += 1except Exception as e:self.log_message.emit(f"轉換失敗 {filename}: {str(e)}")failed += 1finally:if doc:doc.Close()doc = Nonetime.sleep(0.5)except Exception as e:self.log_message.emit(f"Word轉換出錯: {str(e)}")failed += len(words) - successfinally:if doc:try:doc.Close()except:passif word:try:word.Quit()except:passself.log_message.emit("關閉Word進程")time.sleep(1)return success, faileddef convert_excels(self, excels):"""轉換Excel文件為PDF"""success = 0failed = 0excel = Nonewb = Nonews = Nonetry:self.log_message.emit("打開Excel進程...")excel = win32com.client.Dispatch("Excel.Application")excel.Visible = 0excel.DisplayAlerts = Falsefor i, item in enumerate(excels):if not self.is_running:breakfilename = item["name"]file_path = item["path"]self.log_message.emit(f"正在轉換: {filename} ({i+1}/{len(excels)})")from_file = os.path.join(file_path, filename)try:wb = excel.Workbooks.Open(from_file)sheet_count = wb.Worksheets.Countfor j in range(sheet_count):ws = wb.Worksheets(j+1)to_filename = self.add_worksheet_order(filename, j+1)to_file = self.to_file_join(self.output_path, to_filename)ws.ExportAsFixedFormat(0, to_file)  # 0 表示PDF格式self.log_message.emit(f"轉換完成: {to_filename}")success += 1time.sleep(0.5)except Exception as e:self.log_message.emit(f"轉換失敗 {filename}: {str(e)}")failed += 1finally:if ws:try:ws = Noneexcept:passif wb:try:wb.Close(SaveChanges=False)wb = Noneexcept:passtime.sleep(0.5)except Exception as e:self.log_message.emit(f"Excel轉換出錯: {str(e)}")failed += len(excels) - successfinally:if ws:try:ws = Noneexcept:passif wb:try:wb.Close(SaveChanges=False)except:passif excel:try:excel.Quit()except:passself.log_message.emit("關閉Excel進程")time.sleep(1)return success, faileddef convert_ppts(self, ppts):"""轉換PPT文件為PDF(增強版錯誤處理)"""success = 0failed = 0powerpoint = Noneppt = Nonetry:self.log_message.emit("打開PowerPoint進程...")# 創建PowerPoint實例powerpoint = win32com.client.Dispatch("PowerPoint.Application")# 嘗試設置可見性try:powerpoint.Visible = 1  # 顯示窗口self.log_message.emit("PowerPoint窗口已顯示")except Exception as e:self.log_message.emit(f"無法設置PowerPoint可見性: {str(e)}")powerpoint.DisplayAlerts = 0  # 禁用警告for i, item in enumerate(ppts):if not self.is_running:breakfilename = item["name"]file_path = item["path"]self.log_message.emit(f"正在轉換: {filename} ({i+1}/{len(ppts)})")from_file = os.path.abspath(os.path.join(file_path, filename))to_filename = self.change_suffix_to_pdf(filename)to_file = os.path.abspath(self.to_file_join(self.output_path, to_filename))# 檢查文件是否存在if not os.path.exists(from_file):self.log_message.emit(f"文件不存在: {from_file}")failed += 1continue# 檢查文件是否可訪問if not os.access(from_file, os.R_OK):self.log_message.emit(f"沒有文件讀取權限: {from_file}")failed += 1continue# 確保輸出目錄可寫if not os.access(self.output_path, os.W_OK):self.log_message.emit(f"輸出目錄沒有寫入權限: {self.output_path}")failed += 1continue# 確保輸出文件不存在if os.path.exists(to_file):try:os.remove(to_file)self.log_message.emit(f"已刪除已存在的文件: {to_filename}")except Exception as e:self.log_message.emit(f"無法刪除已存在的文件 {to_filename}: {str(e)}")failed += 1continuetry:# 嘗試多種方式打開文件try:# 方式1: 標準打開ppt = powerpoint.Presentations.Open(FileName=from_file,ReadOnly=True,WithWindow=True  # 顯示窗口可能解決權限問題)except:self.log_message.emit("嘗試備用方式打開文件...")# 方式2: 備用打開方式ppt = powerpoint.Presentations.Open(FileName=from_file,ReadOnly=False,WithWindow=True)time.sleep(2)  # 更長延遲確保文件加載if not ppt:raise Exception("無法打開演示文稿")if ppt.Slides.Count == 0:self.log_message.emit(f"跳過空文件: {filename}")failed += 1continue# 嘗試多種轉換方法conversion_methods = [# 方法1: SaveAs PDF格式lambda: ppt.SaveAs(to_file, 32),# 方法2: ExportAsFixedFormat PDF格式lambda: ppt.ExportAsFixedFormat(to_file, 2, Intent=1),# 方法3: 另存為PDF的另一種參數組合lambda: ppt.SaveAs(to_file, 32, EmbedTrueTypeFonts=True)]converted = Falsefor method_idx, convert_method in enumerate(conversion_methods, 1):try:self.log_message.emit(f"嘗試轉換方法 {method_idx}...")convert_method()time.sleep(3)  # 更長延遲確保轉換完成# 檢查文件是否生成if os.path.exists(to_file) and os.path.getsize(to_file) > 0:self.log_message.emit(f"轉換完成: {to_filename}")success += 1converted = Truebreakexcept Exception as e:self.log_message.emit(f"轉換方法 {method_idx} 失敗: {str(e)}")# 刪除可能的空文件if os.path.exists(to_file) and os.path.getsize(to_file) == 0:os.remove(to_file)if not converted:raise Exception("所有轉換方法均失敗")except Exception as e:self.log_message.emit(f"轉換失敗 {filename}: {str(e)}")failed += 1finally:if ppt:try:ppt.Close()ppt = Noneexcept Exception as e:self.log_message.emit(f"關閉PPT時出錯: {str(e)}")time.sleep(1)except Exception as e:self.log_message.emit(f"PPT轉換出錯: {str(e)}")failed += len(ppts) - successfinally:if ppt:try:ppt.Close()except:passif powerpoint:try:# 先關閉所有演示文稿for presentation in powerpoint.Presentations:presentation.Close()# 退出程序powerpoint.Quit()powerpoint = Noneexcept Exception as e:self.log_message.emit(f"關閉PowerPoint時出錯: {str(e)}")# 強制釋放資源gc.collect()time.sleep(1)self.log_message.emit("關閉PowerPoint進程")return success, failed@staticmethoddef change_suffix_to_pdf(file):"""修改文件后綴為PDF"""return file[:file.rfind('.')] + ".pdf"@staticmethoddef add_worksheet_order(file, i):"""為Excel工作表添加序號"""return file[:file.rfind('.')] + f"_工作表{i}.pdf"@staticmethoddef to_file_join(output_path, file):"""生成PDF文件路徑"""return os.path.join(output_path, file)class FileListWidget(QListWidget):"""自定義文件列表部件,支持右鍵刪除"""def __init__(self, parent=None):super().__init__(parent)self.setContextMenuPolicy(Qt.CustomContextMenu)self.customContextMenuRequested.connect(self.show_context_menu)def show_context_menu(self, position):"""顯示右鍵菜單"""menu = QMenu()delete_action = QAction("刪除選中項", self)delete_action.triggered.connect(self.delete_selected_items)delete_action.setFont(QFont("Microsoft YaHei", 10))menu.addAction(delete_action)menu.exec_(self.mapToGlobal(position))def delete_selected_items(self):"""刪除選中的項"""for item in self.selectedItems():row = self.row(item)self.takeItem(row)class OfficeToPdfConverter(QMainWindow):"""Office轉PDF轉換器主窗口"""def __init__(self):super().__init__()# 定義顏色常量(保持原有按鈕風格)self.BUTTON_BLUE = QColor(33, 150, 243)     # 按鈕藍色(#2196F3)self.BUTTON_GREEN = QColor(76, 175, 80)     # 按鈕綠色(#4CAF50)self.BUTTON_RED = QColor(244, 67, 54)       # 按鈕紅色(#f44336)self.LINE_EDIT_BG = QColor(245, 245, 245)   # 文本框背景色(淺灰色)self.worker = Noneself.thread = Noneself.file_items = []  # 存儲文件信息的列表self.init_ui()def init_ui(self):"""初始化用戶界面"""# 設置窗口基本屬性self.setWindowTitle("Office轉PDF轉換器@阿幸")self.setGeometry(100, 100, 900, 800)self.setMinimumSize(700, 600)# 創建主布局main_layout = QVBoxLayout()main_layout.setContentsMargins(20, 20, 20, 20)main_layout.setSpacing(15)# 創建標題title_label = QLabel("Office文件轉PDF轉換器")title_font = QFont("SimHei", 16, QFont.Bold)title_label.setFont(title_font)title_label.setAlignment(Qt.AlignCenter)main_layout.addWidget(title_label)# 創建文件選擇區域file_selection_group = QGroupBox("添加文件或文件夾")file_selection_layout = QVBoxLayout()# 文件操作按鈕(保持原有風格)file_btn_layout = QHBoxLayout()add_file_btn = self.create_button("添加文件", self.add_files, self.BUTTON_BLUE)add_folder_btn = self.create_button("添加目錄", self.add_folder, self.BUTTON_BLUE)clear_btn = self.create_button("清空列表", self.clear_file_list, self.BUTTON_RED)file_btn_layout.addWidget(add_file_btn)file_btn_layout.addWidget(add_folder_btn)file_btn_layout.addWidget(clear_btn)# 文件列表self.file_list_widget = FileListWidget()self.file_list_widget.setAlternatingRowColors(True)self.file_list_widget.setToolTip("右鍵可刪除選中項")file_selection_layout.addLayout(file_btn_layout)file_selection_layout.addWidget(self.file_list_widget)file_selection_group.setLayout(file_selection_layout)main_layout.addWidget(file_selection_group)# 輸出路徑選擇區域output_path_group = QGroupBox("選擇PDF輸出文件夾")output_path_layout = QHBoxLayout()self.output_path_edit = QLineEdit()self.setup_line_edit_bg(self.output_path_edit)self.output_path_edit.setPlaceholderText("請選擇PDF文件的保存位置")# 默認輸出路徑為當前目錄下的pdf子文件夾default_output = os.path.join(os.getcwd(), 'pdf')self.output_path_edit.setText(default_output)browse_output_btn = self.create_button("瀏覽...", self.browse_output_folder, self.BUTTON_BLUE)output_path_layout.addWidget(self.output_path_edit)output_path_layout.addWidget(browse_output_btn)output_path_group.setLayout(output_path_layout)main_layout.addWidget(output_path_group)# 創建文件統計區域stats_group = QGroupBox("文件統計")stats_layout = QFormLayout()self.word_count = QLabel("0")self.excel_count = QLabel("0")self.ppt_count = QLabel("0")self.total_count = QLabel("0")# 設置統計區域字體font = QFont("Microsoft YaHei", 10)self.word_count.setFont(font)self.excel_count.setFont(font)self.ppt_count.setFont(font)self.total_count.setFont(font)stats_layout.addRow("Word文件 (.doc, .docx):", self.word_count)stats_layout.addRow("Excel文件 (.xls, .xlsx):", self.excel_count)stats_layout.addRow("PPT文件 (.ppt, .pptx):", self.ppt_count)stats_layout.addRow("總計可轉換文件:", self.total_count)stats_group.setLayout(stats_layout)main_layout.addWidget(stats_group)# 創建進度條區域progress_layout = QVBoxLayout()self.progress_bar = QProgressBar()self.progress_bar.setValue(0)self.progress_status = QLabel("準備就緒")self.progress_status.setFont(QFont("Microsoft YaHei", 10))self.progress_status.setAlignment(Qt.AlignCenter)progress_layout.addWidget(self.progress_bar)progress_layout.addWidget(self.progress_status)main_layout.addLayout(progress_layout)# 創建按鈕區域(保持原有風格)btn_layout = QHBoxLayout()self.analyze_btn = self.create_button("分析文件", self.analyze_files, self.BUTTON_BLUE, 100)self.convert_btn = self.create_button("開始轉換", self.start_conversion, self.BUTTON_GREEN, 100)self.convert_btn.setEnabled(False)self.cancel_btn = self.create_button("取消", self.cancel_conversion, self.BUTTON_RED, 100)self.cancel_btn.setEnabled(False)btn_layout.addWidget(self.analyze_btn)btn_layout.addWidget(self.convert_btn)btn_layout.addWidget(self.cancel_btn)main_layout.addLayout(btn_layout)# 創建日志區域log_group = QGroupBox("轉換日志")log_layout = QVBoxLayout()self.log_text = QTextEdit()self.log_text.setReadOnly(True)self.log_text.setLineWrapMode(QTextEdit.WidgetWidth)self.log_text.setFont(QFont("Microsoft YaHei", 10))self.setup_line_edit_bg(self.log_text)log_layout.addWidget(self.log_text)log_group.setLayout(log_layout)main_layout.addWidget(log_group)# 設置中心部件central_widget = QWidget()central_widget.setLayout(main_layout)self.setCentralWidget(central_widget)# 狀態欄信息self.statusBar().showMessage("就緒")def create_button(self, text, callback, color, fixed_width=80):"""創建統一風格的按鈕(保持原有風格)"""button = QPushButton(text)button.setFont(QFont("Microsoft YaHei", 10, QFont.Bold))button.setFixedWidth(fixed_width)button.clicked.connect(callback)self.setup_button_style(button, color)return buttondef setup_line_edit_bg(self, widget):"""設置文本框背景顏色(保持原有風格)"""palette = widget.palette()palette.setColor(palette.Base, self.LINE_EDIT_BG)palette.setColor(palette.Text, QColor(0, 0, 0))widget.setPalette(palette)widget.setAutoFillBackground(True)def setup_button_style(self, button, base_color):"""設置按鈕樣式(保持原有風格)"""button.setStyleSheet(f"""QPushButton {{background-color: rgb({base_color.red()}, {base_color.green()}, {base_color.blue()});color: white;border: none;padding: 5px;border-radius: 4px;}}QPushButton:hover {{background-color: rgb({int(base_color.red()*0.8)}, {int(base_color.green()*0.8)}, {int(base_color.blue()*0.8)});}}QPushButton:pressed {{background-color: rgb({int(base_color.red()*0.7)}, {int(base_color.green()*0.7)}, {int(base_color.blue()*0.7)});}}QPushButton:disabled {{background-color: rgb(160, 160, 160);}}""")button.setFocusPolicy(Qt.NoFocus)def add_files(self):"""添加單個或多個文件"""file_paths, _ = QFileDialog.getOpenFileNames(self, "選擇Office文件", os.getcwd(), "Office文件 (*.doc *.docx *.xls *.xlsx *.ppt *.pptx)")if file_paths:added_count = 0for file_path in file_paths:file_dir = os.path.dirname(file_path)file_name = os.path.basename(file_path)# 檢查是否已在列表中is_duplicate = Falsefor i in range(self.file_list_widget.count()):if self.file_list_widget.item(i).data(Qt.UserRole) == file_path:is_duplicate = Truebreakif not is_duplicate:item = QListWidgetItem(file_name)item.setData(Qt.UserRole, file_path)self.file_list_widget.addItem(item)self.file_items.append({"path": file_dir, "name": file_name})added_count += 1if added_count > 0:self.log_text.append(f"已添加 {added_count} 個文件")self.analyze_btn.setEnabled(True)def add_folder(self):"""添加目錄中的所有Office文件"""folder = QFileDialog.getExistingDirectory(self, "選擇文件夾", os.getcwd())if folder:office_extensions = ('.doc', '.docx', '.xls', '.xlsx', '.ppt', '.pptx')added_count = 0for root, _, files in os.walk(folder):for file in files:if file.lower().endswith(office_extensions):file_path = os.path.join(root, file)# 檢查是否已在列表中is_duplicate = Falsefor i in range(self.file_list_widget.count()):if self.file_list_widget.item(i).data(Qt.UserRole) == file_path:is_duplicate = Truebreakif not is_duplicate:item = QListWidgetItem(file)item.setData(Qt.UserRole, file_path)self.file_list_widget.addItem(item)self.file_items.append({"path": root, "name": file})added_count += 1if added_count > 0:self.log_text.append(f"從目錄中添加了 {added_count} 個文件")self.analyze_btn.setEnabled(True)else:QMessageBox.information(self, "提示", "所選目錄中沒有找到可轉換的Office文件")def clear_file_list(self):"""清空文件列表"""if self.file_list_widget.count() > 0:self.file_list_widget.clear()self.file_items = []self.log_text.append("已清空文件列表")self.reset_stats()self.analyze_btn.setEnabled(False)self.convert_btn.setEnabled(False)else:QMessageBox.information(self, "提示", "文件列表已為空")def reset_stats(self):"""重置文件統計"""self.word_count.setText("0")self.excel_count.setText("0")self.ppt_count.setText("0")self.total_count.setText("0")def analyze_files(self):"""分析文件類型并統計數量"""word_count = 0excel_count = 0ppt_count = 0for item in self.file_items:filename = item["name"].lower()if filename.endswith(('.doc', '.docx')):word_count += 1elif filename.endswith(('.xls', '.xlsx')):excel_count += 1elif filename.endswith(('.ppt', '.pptx')):ppt_count += 1total = word_count + excel_count + ppt_countself.word_count.setText(str(word_count))self.excel_count.setText(str(excel_count))self.ppt_count.setText(str(ppt_count))self.total_count.setText(str(total))self.log_text.append(f"文件分析完成: Word {word_count}個, Excel {excel_count}個, PPT {ppt_count}個, 總計 {total}個")if total > 0:self.convert_btn.setEnabled(True)else:self.convert_btn.setEnabled(False)QMessageBox.warning(self, "警告", "沒有可轉換的文件")def browse_output_folder(self):"""選擇輸出文件夾"""folder = QFileDialog.getExistingDirectory(self, "選擇PDF輸出文件夾", os.getcwd())if folder:self.output_path_edit.setText(folder)def start_conversion(self):"""開始轉換任務"""output_path = self.output_path_edit.text().strip()if not output_path:QMessageBox.warning(self, "警告", "請選擇PDF輸出文件夾")returnif not self.file_items:QMessageBox.warning(self, "警告", "請先添加文件")return# 禁用相關按鈕self.analyze_btn.setEnabled(False)self.convert_btn.setEnabled(False)self.cancel_btn.setEnabled(True)# 初始化進度條self.progress_bar.setValue(0)self.progress_status.setText("準備開始轉換...")# 創建線程和工作對象self.thread = QThread()self.worker = ConversionWorker(self.file_items, output_path)self.worker.moveToThread(self.thread)# 連接信號槽self.thread.started.connect(self.worker.run)self.worker.progress_updated.connect(self.update_progress)self.worker.log_message.connect(self.log_text.append)self.worker.conversion_finished.connect(self.conversion_complete)self.worker.conversion_finished.connect(self.thread.quit)self.thread.finished.connect(self.thread.deleteLater)self.thread.finished.connect(lambda: self.worker.deleteLater())# 開始轉換self.thread.start()self.log_text.append("===== 開始轉換 =====")def update_progress(self, value, status):"""更新進度條和狀態"""self.progress_bar.setValue(value)self.progress_status.setText(status)def conversion_complete(self, message):"""轉換完成處理"""self.log_text.append("===== 轉換結束 =====")QMessageBox.information(self, "轉換結果", message)# 恢復按鈕狀態self.analyze_btn.setEnabled(True)self.convert_btn.setEnabled(True)self.cancel_btn.setEnabled(False)self.progress_status.setText("轉換完成")def cancel_conversion(self):"""取消轉換任務"""if self.worker and self.thread and self.thread.isRunning():if QMessageBox.question(self, "確認取消", "確定要取消轉換嗎?", QMessageBox.Yes | QMessageBox.No) == QMessageBox.Yes:self.worker.stop()self.progress_status.setText("正在取消...")self.cancel_btn.setEnabled(False)if __name__ == "__main__":app = QApplication(sys.argv)app.setStyle("Fusion")window = OfficeToPdfConverter()window.show()sys.exit(app.exec_())

軟件下載

夸克
迅雷

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/98920.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/98920.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/98920.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

62_基于深度學習的海洋垃圾檢測識別系統(yolo11、yolov8、yolov5+UI界面+Python項目源碼+模型+標注好的數據集)

目錄 項目介紹🎯 功能展示🌟 一、環境安裝🎆 環境配置說明📘 安裝指南說明🎥 環境安裝教學視頻 🌟 二、數據集介紹🌟 三、系統環境(框架/依賴庫)說明🧱 系統環…

深入淺出 全面剖析消息隊列(Kafka,RabbitMQ,RocketMQ 等)

消息隊列 一、概念 消息隊列(MQ):一種異步通信機制,通過“消息”的形式讓不同系統或模塊解耦核心思想:發送方(生產者Producer)只負責發送消息,接收方(消費者Consumer&…

Flux Images Generation API 對接說明

本文將介紹一種 Flux Images Generation API 對接說明,它是可以通過輸入自定義參數來生成Flux官方的圖片。 接下來介紹下 Flux Images Generation API 的對接說明。 申請流程 要使用 API,需要先到 Flux Images Generation API 對應頁面申請對應的服務…

CSS布局 - 網格布局 -- 筆記3

目錄網格布局基礎網格網格剖析CSS 提供了一些控制網頁布局的幾個重要工具,這里介紹網格布局。 網格布局 CSS 網格可以定義由行和列組成的二維布局,然后將元素放置到網格中。有些元素可能只占據網格的一個單元,另一些元素則可能占據多行或多…

合約開發完后部署測試

一 編譯npx hardhat compile二 測試npx hardhat test三部署注意部署的時候2.0和3版本有所區別,3.0如下# 部署到本地網絡(如已運行 npx hardhat node) npx hardhat ignition deploy ./ignition/modules/MyModule.ts --network localhost# 部署…

產品無法正確解析復雜表格和流程圖,有什么替代方案或優化方法?

在真實辦公場景中,文檔內的元素往往不具備標準化和格式化特征,像雙欄表格、無線圖表等復雜元素十分常見。而傳統 OCR 工具在面對這類復雜文檔時,存在明顯的能力短板:它無法準確判斷復雜表格的結構邏輯以及內容的順序邏輯&#xff…

《Html模板》HTML數學題目生成器 - 讓數學練習更簡單(附源碼)

目錄專欄導讀🧮 HTML數學題目生成器 - 讓數學練習更簡單項目簡介? 核心功能🎯 靈活的運算類型選擇📊 智能題目生成算法?? 個性化參數設置🖨? 專業打印優化🎨 用戶體驗設計現代化界面交互體驗🛠? 技術實…

Go語言設計模式(七)組合模式

組合模式是指將一組相似對象當做一個單一對象的設計模式.1.組成角色:1.1組件:組合中的對象聲明接口,主要用于訪問和管理其子組件.1.2葉子節點:定義組合中原始對象行為的類.葉子節點表示組合中的葉對象.1.3組合:又稱為容器,存儲子組件并在組件接口中實現與子組件有關的類.1.4客戶…

AI 3D 生成工具知識庫:當前產品格局與測評總結

聚焦于 AI 3D 生成領域的領軍產品、功能比較及實測性能。內容分為產品格局、通用功能、測評系統與基準測試,以及單視圖生成實測結果。所有信息基于腳本分析,并交叉驗證了產品名稱、團隊背景(如 VAST AI 的 TripoSR/Meshy 的 Meshy-1、影眸科技…

淘客app的容器化部署與編排:基于Kubernetes的微服務架構實踐

淘客app的容器化部署與編排:基于Kubernetes的微服務架構實踐 大家好,我是阿可,微賺淘客系統及省賺客APP創始人,是個冬天不穿秋褲,天冷也要風度的程序猿! 在淘客app的業務迭代中,傳統物理機部署面…

當GitHub不再純粹:Python自動化測試的未來是AI還是危機?

全球最大的開源代碼平臺,徹底被卷進了AI洪流!作為全球最大的“程序員交友平臺”(手動狗頭),GitHub 可以說是每一個開發者又愛又恨的“家”。沒錯,就是那個全球最大、沒有之一的開源代碼托管平臺&#xff01…

Spring Boot + MySQL 創建超級管理員

Spring Boot系統創建超管實現方式1. 數據庫腳本初始化(最直接的方式)2. Spring Boot 啟動時自動創建(代碼級初始化)2.1 實體類定義2.2 Repository 接口2.3 初始化組件2.4 配置密碼加密器3. 通過接口手動創建(最安全的方…

楊輝三角**

一、題目給定一個非負整數 numRows&#xff0c;生成「楊輝三角」的前 numRows 行。在「楊輝三角」中&#xff0c;每個數是它左上方和右上方的數的和。示例 1:輸入: numRows 5 輸出: [[1],[1,1],[1,2,1],[1,3,3,1],[1,4,6,4,1]]示例 2:輸入: numRows 1 輸出: [[1]]提示:1 <…

Vue3 的單文件組件(.vue 文件)中,在 <script>、<template>、<style> 標簽外輸入內容不會導致程序報錯

在 <script>、<template>、<style> 標簽外首行誤輸入內容 vtsvts <script setup lang"ts" name"BaseDocxPreviewDialog"> /*** docx文件預覽模態框組件*/ defineOptions({ name: "BaseDocxPreviewDialog" }); import { …

LVS負載均衡群集和LVS+Keepalived群集

1、群集 1.1群集的含義 由多臺主機構成&#xff0c;但對外只表現為一個整體&#xff0c;只提供一個訪問入口&#xff08;域名與IP地址&#xff09;&#xff0c;相當于一臺大型計算機。 1.2 企業群集分類 負載均衡群集&#xff1a;提高應用系統的響應能力、盡可能處理更多的…

LeetCode力扣-hot100系列(5)

這一篇主要講一講回溯&#xff0c;除了N皇后問題是困難題&#xff0c;不過N皇后知道了咋做也不難。回溯整體上還是好做的&#xff0c;直到套路容易做出來&#xff0c;題目容易理解。回溯[1]全排列問&#xff1a;給定一個不含重復數字的數組 nums &#xff0c;返回其 所有可能的…

機器學習05——多分類學習與類別不平衡(一對一、一對其余、多對多)

上一章&#xff1a;機器學習04——決策樹 下一章&#xff1a;機器學習06——支持向量機 機器學習實戰項目&#xff1a;【從 0 到 1 落地】機器學習實操項目目錄&#xff1a;覆蓋入門到進階&#xff0c;大學生就業 / 競賽必備 文章目錄一、多分類學習&#xff08;一&#xff09;…

2025.9.11總結

閱讀《拿鐵因素》有感昨天看完《拿鐵因素》&#xff0c;這本書讓我明白&#xff0c;如果不去主動去管理自己的財務&#xff0c;解決自己從前的財務問題&#xff0c;我很難過上自己想要的生活。今天就所讀的內容&#xff0c;探究如何將這本書的內容運用到自己的一個日常生活中。…

Android,Jetpack Compose,坦克大戰游戲案例Demo

代碼如下&#xff08;這只是個簡單案例而已&#xff09;&#xff1a; package com.example.myapplicationimport android.os.Bundle import androidx.activity.ComponentActivity import androidx.activity.compose.setContent import androidx.compose.foundation.Canvas impo…

zookeeper是啥

ZooKeeper是一個開源的分布式協調服務&#xff0c;主要用于解決分布式系統中的數據一致性、狀態同步和協作問題?。它通過提供高可用、強一致性的服務&#xff0c;成為分布式系統的“指揮中心”?。以下是其核心功能和應用場景&#xff1a;核心功能 分布式同步? 通過原子廣播協…