这个输出,把PDF,word,l图片 取消

本文阐述了普通报表与全局配置的区别,普通报表通过模板及其Web属性进行设置,而全局配置则是在服务器层面进行调整。

普通报表是: 模板 -> 模板Web属性

全局的话,就是在服务器 -> 服务器配置

 

import os import sys import time import subprocess from pathlib import Path from docx2pdf import convert from concurrent.futures import ThreadPoolExecutor, as_completed from tqdm import tqdm from datetime import timedelta # 全局统计变量 global_start_time = None total_conversion_time = 0 file_conversion_times = [] class WordToPDFConverter: """使用docx2pdf或LibreOffice进行高质量转换""" def __init__(self, word_path, pdf_path=None): self.word_path = os.path.abspath(word_path) if pdf_path is None: pdf_path = os.path.splitext(word_path)[0] + '.pdf' self.pdf_path = os.path.abspath(pdf_path) self.start_time = None self.end_time = None def convert_using_docx2pdf(self): """使用docx2pdf库(依赖Word或LibreOffice)""" try: self.start_time = time.time() # docx2pdf内部会处理转换,不需要额外初始化 convert(self.word_path, self.pdf_path) self.end_time = time.time() return True except Exception as e: print(f"docx2pdf转换失败: {e}") return False def convert_using_libreoffice_fast(self): """使用LibreOffice(跨平台)- 快速版本""" try: self.start_time = time.time() # 构建命令行参数(优化版本) if sys.platform == 'win32': # Windows系统尝试多个可能的LibreOffice路径 lo_paths = [ r"C:\Program Files\LibreOffice\program\soffice.exe", r"C:\Program Files (x86)\LibreOffice\program\soffice.exe", r"C:\Program Files\LibreOffice 7\program\soffice.exe", r"C:\Program Files\LibreOffice 24\program\soffice.exe", r"C:\Program Files\LibreOffice 8\program\soffice.exe" ] # 查找可用的LibreOffice路径 soffice_path = "soffice.exe" for lo_path in lo_paths: if os.path.exists(lo_path): soffice_path = lo_path break cmd = [ soffice_path, '--headless', # 无界面模式 '--nologo', # 不显示logo '--nodefault', # 不加载默认模板 '--nofirststartwizard', # 跳过首次启动向导 '--nolockcheck', # 不检查文件锁定 '--invisible', # 完全不可见模式 '--norestore', # 不恢复会话 '--convert-to', 'pdf', '--outdir', os.path.dirname(self.pdf_path), self.word_path ] else: # Linux/Mac系统 cmd = [ 'soffice', '--headless', '--nologo', '--nodefault', '--nofirststartwizard', '--nolockcheck', '--invisible', '--norestore', '--convert-to', 'pdf', '--outdir', os.path.dirname(self.pdf_path), self.word_path ] # 使用subprocess快速执行 result = subprocess.run( cmd, capture_output=True, text=True, shell=True, timeout=30 # 设置超时防止卡住 ) if result.returncode == 0: # 重命名输出文件 base_name = os.path.splitext(os.path.basename(self.word_path))[0] temp_pdf = os.path.join(os.path.dirname(self.pdf_path), f"{base_name}.pdf") if os.path.exists(temp_pdf) and temp_pdf != self.pdf_path: os.rename(temp_pdf, self.pdf_path) self.end_time = time.time() return True else: print(f"LibreOffice转换失败: {result.stderr}") return False except subprocess.TimeoutExpired: print(f"LibreOffice转换超时: {self.word_path}") return False except Exception as e: print(f"LibreOffice转换失败: {e}") return False def convert(self, method='auto', fast_mode=True): """ 执行转换 Args: method: 'auto', 'docx2pdf', 'libreoffice' fast_mode: 是否启用快速模式 """ if not os.path.exists(self.word_path): raise FileNotFoundError(f"Word文件不存在: {self.word_path}") # 确保输出目录存在 os.makedirs(os.path.dirname(self.pdf_path) or '.', exist_ok=True) # 检查文件扩展名 if not self.word_path.lower().endswith(('.docx', '.doc')): print(f"不支持的文件格式: {self.word_path}") return False # 记录开始时间 self.start_time = time.time() # 根据选择的方法进行转换 if method == 'docx2pdf': result = self.convert_using_docx2pdf() elif method == 'libreoffice': result = self.convert_using_libreoffice_fast() elif method == 'auto': # 自动选择:先尝试docx2pdf,失败则使用LibreOffice try: result = self.convert_using_docx2pdf() if not result: result = self.convert_using_libreoffice_fast() except: result = self.convert_using_libreoffice_fast() else: raise ValueError(f"不支持的转换方法: {method}") # 记录结束时间 self.end_time = time.time() # 记录转换时间 if self.start_time and self.end_time: conversion_time = self.end_time - self.start_time file_conversion_times.append((self.word_path, conversion_time)) return result def batch_convert_folder_fast(input_folder, output_folder=None, method='auto', max_workers=4, batch_size=5): """ 快速批量转换指定文件夹中的所有Word文件为PDF Args: input_folder: 包含Word文件的文件夹路径 output_folder: 输出PDF的文件夹路径(可选) method: 转换方法 'auto', 'docx2pdf', 'libreoffice' max_workers: 最大并发线程数 batch_size: 每批处理的文件数 """ global global_start_time, total_conversion_time # 记录全局开始时间 global_start_time = time.time() # 确保输入文件夹存在 input_path = Path(input_folder) if not input_path.exists(): print(f"错误:文件夹不存在 - {input_folder}") return # 设置输出文件夹 if output_folder is None: output_path = input_path / "pdf_output_fast" else: output_path = Path(output_folder) # 创建输出文件夹 output_path.mkdir(parents=True, exist_ok=True) # 查找所有Word文件 word_files = [] for ext in ['.docx', '.doc']: word_files.extend(input_path.glob(f"*{ext}")) # 按文件大小排序,小文件优先处理 word_files.sort(key=lambda x: x.stat().st_size if x.exists() else 0) if not word_files: print(f"在 '{input_folder}' 中没有找到Word文件!") print("支持的文件格式: .docx, .doc") return # 显示转换方法信息 method_info = { 'docx2pdf': 'docx2pdf(需要Microsoft Word或LibreOffice)', 'libreoffice': 'LibreOffice命令行', 'auto': '自动选择(推荐)' } print("=" * 60) print("🚀 高速WordPDF批量转换工具") print("=" * 60) print(f"📁 输入文件夹: {input_folder}") print(f"📂 输出文件夹: {output_folder if output_folder else output_path}") print(f"📄 找到 {len(word_files)} 个Word文件") print(f"🔄 转换方法: {method} - {method_info.get(method, method)}") print(f"⚡ 并发线程: {max_workers}") print(f"📦 批处理大小: {batch_size}") print("-" * 60) # 分批次处理 batches = [] for i in range(0, len(word_files), batch_size): batches.append(word_files[i:i + batch_size]) print(f"📊 分成了 {len(batches)} 个批次进行转换") # 统计信息 success_count = 0 failed_files = [] batch_times = [] # 处理每个批次 for batch_num, batch in enumerate(batches, 1): batch_start = time.time() print(f"\n📦 批次 {batch_num}/{len(batches)}: {len(batch)} 个文件") batch_success = 0 batch_failed = [] if max_workers > 1 and len(batch) > 1: # 多线程处理批次 with ThreadPoolExecutor(max_workers=min(max_workers, len(batch))) as executor: # 创建任务 futures = [] for word_file in batch: pdf_file = output_path / f"{word_file.stem}.pdf" future = executor.submit(convert_single_file_fast, str(word_file), str(pdf_file), method) futures.append((word_file, future)) # 等待结果 for word_file, future in tqdm(futures, desc=f"批次{batch_num}", unit="文件"): try: success, conversion_time = future.result(timeout=60) if success: batch_success += 1 else: batch_failed.append(word_file.name) except Exception as e: batch_failed.append(word_file.name) print(f"文件 {word_file.name} 处理异常: {e}") else: # 单线程处理 for word_file in tqdm(batch, desc=f"批次{batch_num}", unit="文件"): try: pdf_file = output_path / f"{word_file.stem}.pdf" converter = WordToPDFConverter(str(word_file), str(pdf_file)) if converter.convert(method=method, fast_mode=True): batch_success += 1 else: batch_failed.append(word_file.name) except Exception as e: batch_failed.append(word_file.name) print(f"文件 {word_file.name} 转换出错: {e}") batch_end = time.time() batch_time = batch_end - batch_start batch_times.append(batch_time) success_count += batch_success failed_files.extend(batch_failed) print(f" ✅ 成功: {batch_success}/{len(batch)}") print(f" ⏱️ 耗时: {batch_time:.2f} 秒") print(f" 📈 速度: {len(batch)/batch_time:.2f} 文件/秒" if batch_time > 0 else "") # 计算总耗时 total_end_time = time.time() total_conversion_time = total_end_time - global_start_time # 输出结果 print("\n" + "=" * 60) print("🎉 批量转换完成!") print("=" * 60) print(f"📊 统计信息:") print(f" 总文件数: {len(word_files)}") print(f" 成功: {success_count}") print(f" 失败: {len(failed_files)}") print(f" 总用时: {total_conversion_time:.2f} 秒") print(f" 平均速度: {len(word_files)/total_conversion_time:.2f} 文件/秒") print(f" 输出位置: {output_path}") # 显示时间分析 if file_conversion_times: print(f"\n⏱️ 时间分析:") print(f" 最快文件: {min(t for _, t in file_conversion_times):.2f} 秒") print(f" 最慢文件: {max(t for _, t in file_conversion_times):.2f} 秒") print(f" 平均时间: {sum(t for _, t in file_conversion_times)/len(file_conversion_times):.2f} 秒/文件") # 显示最慢的几个文件 slowest_files = sorted(file_conversion_times, key=lambda x: x[1], reverse=True)[:3] if slowest_files: print(f" 🐌 最慢的3个文件:") for file_path, t in slowest_files: filename = os.path.basename(file_path) print(f" {filename}: {t:.2f} 秒") if failed_files: print(f"\n📝 失败的文件 ({len(failed_files)}个):") for i, file in enumerate(failed_files[:10], 1): # 只显示前10个 print(f" {i:2d}. {file}") if len(failed_files) > 10: print(f" ... 还有 {len(failed_files)-10} 个文件") # 生成详细报告文件 report_path = output_path / "conversion_report_detailed.txt" with open(report_path, 'w', encoding='utf-8') as f: f.write("=" * 60 + "\n") f.write("WordPDF批量转换详细报告\n") f.write("=" * 60 + "\n\n") f.write(f"转换时间: {time.strftime('%Y-%m-%d %H:%M:%S')}\n") f.write(f"输入文件夹: {input_folder}\n") f.write(f"输出文件夹: {output_path}\n") f.write(f"转换方法: {method}\n") f.write(f"并发线程: {max_workers}\n") f.write(f"批处理大小: {batch_size}\n\n") f.write(f"总文件数: {len(word_files)}\n") f.write(f"成功转换: {success_count}\n") f.write(f"转换失败: {len(failed_files)}\n") f.write(f"总用时: {total_conversion_time:.2f} 秒\n") f.write(f"平均速度: {len(word_files)/total_conversion_time:.2f} 文件/秒\n\n") # 批次时间统计 f.write("批次处理时间:\n") for i, batch_time in enumerate(batch_times, 1): f.write(f" 批次 {i}: {batch_time:.2f} 秒\n") f.write(f"\n平均批次时间: {sum(batch_times)/len(batch_times):.2f} 秒\n") if file_conversion_times: f.write("\n文件转换时间统计:\n") f.write("-" * 40 + "\n") total_file_time = sum(t for _, t in file_conversion_times) for file_path, conv_time in file_conversion_times: filename = os.path.basename(file_path) f.write(f"{filename:<40} {conv_time:6.2f} 秒\n") f.write("-" * 40 + "\n") f.write(f"{'总计':<40} {total_file_time:6.2f} 秒\n") f.write(f"{'平均':<40} {total_file_time/len(file_conversion_times):6.2f} 秒\n") if failed_files: f.write(f"\n失败文件列表 ({len(failed_files)}个):\n") f.write("-" * 40 + "\n") for file in failed_files: f.write(f"- {file}\n") print(f"\n📋 详细报告已保存到: {report_path}") # 显示性能总结 print("\n" + "=" * 60) print("📈 性能总结:") print(f" 总处理时间: {timedelta(seconds=int(total_conversion_time))}") print(f" 处理效率: {len(word_files)/total_conversion_time:.2f} 文件/秒") if file_conversion_times: print(f" 系统开销: {total_conversion_time - sum(t for _, t in file_conversion_times):.2f} 秒") print("=" * 60) def convert_single_file_fast(word_path, pdf_path, method='auto'): """快速转换单个文件(用于多线程)""" try: converter = WordToPDFConverter(word_path, pdf_path) success = converter.convert(method=method, fast_mode=True) # 返回成功状态和转换时间 conversion_time = converter.end_time - converter.start_time if converter.end_time and converter.start_time else 0 return success, conversion_time except Exception as e: print(f"文件 {os.path.basename(word_path)} 转换出错: {e}") return False, 0 def check_docx2pdf_available(): """检查docx2pdf是否可用""" try: from docx2pdf import convert return True except ImportError: return False def check_libreoffice_available(): """检查LibreOffice是否可用""" try: if sys.platform == 'win32': lo_paths = [ r"C:\Program Files\LibreOffice\program\soffice.exe", r"C:\Program Files (x86)\LibreOffice\program\soffice.exe", r"C:\Program Files\LibreOffice 7\program\soffice.exe" ] for lo_path in lo_paths: if os.path.exists(lo_path): return True else: # Linux/Mac系统 result = subprocess.run(['which', 'soffice'], capture_output=True) return result.returncode == 0 except: pass return False def show_conversion_method_menu(): """显示转换方法选择菜单""" print("\n" + "=" * 60) print("📋 请选择转换方法:") print("=" * 60) # 检查各方法是否可用 docx2pdf_available = check_docx2pdf_available() libreoffice_available = check_libreoffice_available() print(f"1. docx2pdf方法") print(f" {'✅ 可用' if docx2pdf_available else '❌ 不可用'}") print(f" - 基于Microsoft Word或LibreOffice") print(f" - 转换质量高,支持复杂格式") print(f" - 需要安装Microsoft Word或LibreOffice") print(f"\n2. LibreOffice命令行方法") print(f" {'✅ 可用' if libreoffice_available else '❌ 不可用'}") print(f" - 直接使用LibreOffice命令行") print(f" - 开源免费,跨平台") print(f" - 需要安装LibreOffice") print(f"\n3. 自动选择(推荐)") print(f" {'✅ 可用' if docx2pdf_available or libreoffice_available else '❌ 不可用'}") print(f" - 自动选择可用的最佳方法") print(f" - 先尝试docx2pdf,失败则使用LibreOffice") print("\n" + "-" * 60) # 根据可用情况显示选项 available_options = [] if docx2pdf_available: available_options.append(("docx2pdf", "1")) if libreoffice_available: available_options.append(("libreoffice", "2")) if docx2pdf_available or libreoffice_available: available_options.append(("auto", "3")) while True: choice = input("\n请选择转换方法 (输入数字或名称,回车使用自动选择): ").strip() if not choice: return 'auto' # 检查数字选择 if choice == '1' and docx2pdf_available: return 'docx2pdf' elif choice == '2' and libreoffice_available: return 'libreoffice' elif choice == '3': return 'auto' # 检查名称选择 choice_lower = choice.lower() if choice_lower == 'docx2pdf' and docx2pdf_available: return 'docx2pdf' elif choice_lower == 'libreoffice' and libreoffice_available: return 'libreoffice' elif choice_lower == 'auto': return 'auto' print("❌ 无效选择或该方法不可用,请重新选择") def interactive_batch_convert(): """交互式批量转换""" print("🚀 WordPDF批量转换工具") print("=" * 60) # 获取输入文件夹 while True: input_folder = input("请输入Word文件所在文件夹路径: ").strip() if not input_folder: input_folder = os.getcwd() print(f"使用当前文件夹: {input_folder}") break input_path = Path(input_folder) if input_path.exists(): # 检查文件夹中是否有Word文件 word_files = list(input_path.glob("*.docx")) + list(input_path.glob("*.doc")) if word_files: print(f"✅ 找到 {len(word_files)} 个Word文件") break else: print(f"⚠️ 文件夹中没有找到Word文件,支持的文件格式: .docx, .doc") print("请检查路径是否正确,或按回车使用当前文件夹") else: print("❌ 文件夹不存在,请重新输入") # 获取输出文件夹 default_output = str(Path(input_folder) / "pdf_output") output_folder = input(f"PDF输出文件夹 (回车使用 '{default_output}'): ").strip() if not output_folder: output_folder = default_output # 选择转换方法 conversion_method = show_conversion_method_menu() # 配置参数选择 print("\n⚙️ 配置转换参数:") print("-" * 40) # 选择线程数 cpu_count = os.cpu_count() or 4 while True: threads_input = input(f"并发线程数 (1-{cpu_count*2},回车使用4): ").strip() if not threads_input: max_workers = 4 break try: max_workers = int(threads_input) if 1 <= max_workers <= cpu_count * 2: break else: print(f"请输入1到{cpu_count*2}之间的数字") except ValueError: print("请输入有效的数字") # 选择批次大小 while True: batch_input = input("每批处理的文件数 (1-50,回车使用10): ").strip() if not batch_input: batch_size = 10 break try: batch_size = int(batch_input) if 1 <= batch_size <= 50: break else: print("请输入1到50之间的数字") except ValueError: print("请输入有效的数字") # 显示配置摘要 print("\n" + "=" * 60) print("📋 配置摘要:") print("=" * 60) print(f"输入文件夹: {input_folder}") print(f"输出文件夹: {output_folder}") print(f"转换方法: {conversion_method}") print(f"并发线程: {max_workers}") print(f"批次大小: {batch_size}") print(f"开始时间: {time.strftime('%Y-%m-%d %H:%M:%S')}") print("=" * 60) # 确认开始转换 confirm = input("\n是否开始转换?(y/n,回车开始): ").strip().lower() if confirm == 'n': print("转换已取消") return print("\n🚀 开始转换...") print("-" * 60) # 开始转换 batch_convert_folder_fast( input_folder=input_folder, output_folder=output_folder, method=conversion_method, max_workers=max_workers, batch_size=batch_size ) # ==================== 简单批量转换函数(优化版) ==================== def simple_batch_convert_fast(): """ 简单的批量转换函数 - 直接调用即可(优化版) """ # 设置您的文件夹路径(修改这里) input_folder = r"E:\导师任务\lj\111\4" # Word文件所在文件夹 output_folder = r"E:\PyCharm Projects\pdf2" # 输出文件夹(可选,不填则自动创建) # 用户选择转换方法 print("\n" + "=" * 60) print("🔧 请选择转换方法:") print("=" * 60) print("1. docx2pdf方法(推荐,需要Microsoft Word或LibreOffice)") print("2. LibreOffice命令行方法(开源免费)") print("3. 自动选择(推荐,自动选择最佳方法)") print("=" * 60) while True: choice = input("\n请选择转换方法 (1/2/3,回车使用自动选择): ").strip() if not choice or choice == '3': method = 'auto' break elif choice == '1': method = 'docx2pdf' break elif choice == '2': method = 'libreoffice' break else: print("❌ 无效选择,请输入1、2或3") # 开始高速批量转换 print(f"\n🚀 开始高速转换: {input_folder}") print(f"📂 输出到: {output_folder}") print(f"🔄 使用: {method} 方法") print(f"⏱️ 开始时间: {time.strftime('%Y-%m-%d %H:%M:%S')}") print("-" * 60) batch_convert_folder_fast( input_folder=input_folder, output_folder=output_folder, method=method, # 用户选择的转换方法 max_workers=4, # 并发线程数(根据CPU核心数调整) batch_size=10 # 每批处理的文件数 ) # ==================== 命令行支持 ==================== def main(): """ 主函数,支持命令行参数 使用方式: python wordpdf.py [输入文件夹] [输出文件夹] [转换方法] 示例: python wordpdf.py "E:\文档" "E:\输出" "docx2pdf" """ if len(sys.argv) > 1: # 使用命令行参数 input_folder = sys.argv[1] output_folder = sys.argv[2] if len(sys.argv) > 2 else None method = sys.argv[3] if len(sys.argv) > 3 else 'auto' # 验证方法参数 if method not in ['auto', 'docx2pdf', 'libreoffice']: print(f"❌ 无效的转换方法: {method}") print("可用的方法: auto, docx2pdf, libreoffice") method = 'auto' print(f"使用命令行参数:") print(f"输入文件夹: {input_folder}") print(f"输出文件夹: {output_folder if output_folder else '自动创建'}") print(f"转换方法: {method}") print("=" * 60) batch_convert_folder_fast( input_folder=input_folder, output_folder=output_folder, method=method, max_workers=4, batch_size=10 ) else: # 交互式使用 interactive_batch_convert() # ==================== 快速测试函数 ==================== def quick_test(): """快速测试转换功能""" print("🔧 快速测试WordPDF功能...") # 创建测试文件夹 test_folder = Path("test_docs") test_folder.mkdir(exist_ok=True) # 检查当前文件夹中的Word文件 input_folder = os.getcwd() word_files = list(Path(input_folder).glob("*.docx")) + list(Path(input_folder).glob("*.doc")) if word_files: print(f"找到 {len(word_files)} 个Word文件") print("请选择要测试的转换方法:") # 检查可用方法 docx2pdf_available = check_docx2pdf_available() libreoffice_available = check_libreoffice_available() if not docx2pdf_available and not libreoffice_available: print("❌ 没有可用的转换方法,请安装Microsoft Word或LibreOffice") return print("1. 测试docx2pdf方法" + (" (可用)" if docx2pdf_available else " (不可用)")) print("2. 测试LibreOffice方法" + (" (可用)" if libreoffice_available else " (不可用)")) while True: choice = input("\n请选择测试方法 (1/2): ").strip() if choice == '1' and docx2pdf_available: method = 'docx2pdf' break elif choice == '2' and libreoffice_available: method = 'libreoffice' break else: print("❌ 无效选择或该方法不可用") # 测试第一个文件 test_file = word_files[0] output_file = test_folder / f"{test_file.stem}_test_{method}.pdf" print(f"\n测试文件: {test_file.name}") print(f"测试方法: {method}") print(f"输出文件: {output_file}") print("-" * 40) converter = WordToPDFConverter(str(test_file), str(output_file)) if converter.convert(method): print(f"✅ 测试成功!文件已转换到: {output_file}") print(f"⏱️ 转换用时: {converter.end_time - converter.start_time:.2f} 秒") else: print("❌ 测试失败,请检查安装和配置") else: print("⚠️ 当前文件夹中没有找到Word文件") print("请将Word文件放在当前文件夹中,或指定文件夹路径") # ==================== 主程序入口 ==================== if __name__ == "__main__": print("🚀 WordPDF批量转换工具 v2.0") print("=" * 60) print("功能:") print("1. 批量转换文件夹中的所有Word文件") print("2. 支持docx2pdf和LibreOffice两种方法") print("3. 自动选择最佳转换方法") print("4. 显示详细的时间统计和性能分析") print("=" * 60) # 显示菜单 print("\n请选择操作模式:") print("1. 交互式批量转换(推荐)") print("2. 简单批量转换(预设路径)") print("3. 快速测试转换功能") print("4. 命令行模式") print("=" * 60) while True: mode = input("\n请选择操作模式 (1/2/3/4,回车使用交互式): ").strip() if not mode or mode == '1': interactive_batch_convert() break elif mode == '2': simple_batch_convert_fast() break elif mode == '3': quick_test() break elif mode == '4': print("\n命令行模式:") print("用法: python wordpdf.py [输入文件夹] [输出文件夹] [转换方法]") print("示例: python wordpdf.py \"E:\\文档\" \"E:\\输出\" \"docx2pdf\"") print("转换方法: auto, docx2pdf, libreoffice") break else: print("❌ 无效选择,请输入1、2、3或4")
12-04
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值