JinFeng_Report_Generate/tools/win32_total_copy.py

173 lines
6.7 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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}")
return output_path
except Exception as e:
logger.error(f"文档合并失败: {str(e)}", exc_info=True)
return None
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("合并失败,请查看日志文件。")