JinFeng_Report_Generate/tools/win32_total_copy.py

173 lines
6.7 KiB
Python
Raw Normal View History

2025-07-02 16:02:36 +08:00
import win32com.client as win32
import pythoncom
import logging
from pathlib import Path
# 配置日志
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(levelname)s - %(message)s',
handlers=[
logging.FileHandler('docx_merge_win32com.log'),
logging.StreamHandler()
]
)
logger = logging.getLogger(__name__)
# Word常量定义如果无法从constants模块获取
class WordConstants:
wdCollapseEnd = 0
wdSectionBreakNextPage = 2
wdHeaderFooterPrimary = 1
wdHeaderFooterFirstPage = 2
wdHeaderFooterEvenPages = 3
wdBorderBottom = -3 # 下边框常量
wdLineStyleSingle = 1 # 单线样式
class WordDocumentMerger:
def __init__(self):
# 初始化COM对象
pythoncom.CoInitialize()
self.word_app = win32.DispatchEx('Word.Application')
self.word_app.Visible = False
self.word_app.DisplayAlerts = False
self.constants = WordConstants()
def merge_documents(self, doc1_path, doc2_path, output_path):
"""合并两个Word文档"""
doc1 = doc2 = None
try:
logger.info(f"开始合并文档: {doc1_path}{doc2_path}")
# 打开文档
doc1 = self.word_app.Documents.Open(str(doc1_path))
logger.info(f"已打开第一个文档: {doc1_path}")
doc2 = self.word_app.Documents.Open(str(doc2_path))
logger.info(f"已打开第二个文档: {doc2_path}")
# 插入第二个文档的内容
self._insert_document_content(doc1, doc2)
# 特别处理页眉格式
self._fix_header_borders(doc1)
# 保存合并后的文档
output_path = self._ensure_unique_filename(output_path)
doc1.SaveAs(str(output_path))
logger.info(f"已保存合并文档: {output_path}")
2025-07-08 10:44:37 +08:00
return output_path
2025-07-02 16:02:36 +08:00
except Exception as e:
logger.error(f"文档合并失败: {str(e)}", exc_info=True)
2025-07-08 10:44:37 +08:00
return None
2025-07-02 16:02:36 +08:00
finally:
self._cleanup(doc1, doc2)
def _insert_section_break(self, doc):
"""在文档末尾插入分节符"""
try:
end_range = doc.Content
end_range.Collapse(Direction=self.constants.wdCollapseEnd)
end_range.InsertBreak(Type=self.constants.wdSectionBreakNextPage)
logger.debug("已插入分节符")
except Exception as e:
logger.error(f"插入分节符失败: {str(e)}")
raise
def _insert_document_content(self, target_doc, source_doc):
"""插入文档内容"""
try:
source_range = source_doc.Content
target_range = target_doc.Content
target_range.Collapse(Direction=self.constants.wdCollapseEnd)
source_range.Copy()
target_range.Paste()
logger.info("已插入第二个文档内容")
# 合并页眉页脚
self._merge_headers_footers(target_doc, source_doc)
except Exception as e:
logger.error(f"插入文档内容失败: {str(e)}")
raise
def _merge_headers_footers(self, target_doc, source_doc):
"""合并页眉页脚"""
try:
last_section = target_doc.Sections(target_doc.Sections.Count)
src_section = source_doc.Sections(1)
# 合并页眉
for header_type in [self.constants.wdHeaderFooterPrimary,
self.constants.wdHeaderFooterFirstPage,
self.constants.wdHeaderFooterEvenPages]:
if src_section.Headers(header_type).Exists:
src_section.Headers(header_type).Range.Copy()
last_section.Headers(header_type).Range.Paste()
# 合并页脚
for footer_type in [self.constants.wdHeaderFooterPrimary,
self.constants.wdHeaderFooterFirstPage,
self.constants.wdHeaderFooterEvenPages]:
if src_section.Footers(footer_type).Exists:
src_section.Footers(footer_type).Range.Copy()
last_section.Footers(footer_type).Range.Paste()
logger.info("已合并页眉页脚")
except Exception as e:
logger.error(f"合并页眉页脚失败: {str(e)}")
raise
def _fix_header_borders(self, doc):
"""确保所有页眉都有底部边框线"""
try:
for section in doc.Sections:
for header_type in [self.constants.wdHeaderFooterPrimary,
self.constants.wdHeaderFooterFirstPage]:
if section.Headers(header_type).Exists:
header = section.Headers(header_type).Range
if header.Paragraphs.Count > 0:
border = header.Paragraphs(1).Borders(
self.constants.wdBorderBottom)
border.LineStyle = self.constants.wdLineStyleSingle
border.LineWidth = 4
logger.info("已修复所有页眉边框线")
except Exception as e:
logger.error(f"修复页眉边框失败: {str(e)}")
def _ensure_unique_filename(self, path):
"""确保文件名唯一"""
path = Path(path)
if not path.exists():
return path
counter = 1
while True:
new_path = path.parent / f"{path.stem}_{counter}{path.suffix}"
if not new_path.exists():
return new_path
counter += 1
def _cleanup(self, *docs):
"""清理资源"""
try:
for doc in docs:
if doc and hasattr(doc, 'Close'):
doc.Close(SaveChanges=False)
if hasattr(self, 'word_app') and self.word_app:
self.word_app.Quit()
pythoncom.CoUninitialize()
logger.info("已清理资源")
except Exception as e:
logger.error(f"清理资源失败: {str(e)}")
# if __name__ == "__main__":
# merger = WordDocumentMerger()
# # 修改为您的实际文件路径
# doc1_path = Path(r"C:\Users\VogelimKafig\Desktop\金风模板\jingfeng_fengmian1.docx")
# doc2_path = Path(r"C:\Users\VogelimKafig\Desktop\金风模板\quexian.docx")
# output_path = Path(r"C:\Users\VogelimKafig\Desktop\金风模板\merged_document.docx")
# if merger.merge_documents(doc1_path, doc2_path, output_path):
# print(f"合并成功! 输出文件: {output_path}")
# else:
# print("合并失败,请查看日志文件。")