使用Python實現(xiàn)Word文檔的深度克隆的完整代碼
核心功能概述
該腳本實現(xiàn)了以下核心功能:
- 段落樣式克隆:完整復(fù)制字體、顏色、加粗、斜體等格式
- 表格格式遷移:包括單元格邊框、列寬、對齊方式等
- 分頁符識別處理:自動識別并復(fù)制分頁符
- 文檔結(jié)構(gòu)維護:保持原始文檔的層級結(jié)構(gòu)
代碼解析
1. 基礎(chǔ)樣式復(fù)制
def copy_paragraph_style(run_from, run_to):
"""復(fù)制 run 的樣式"""
run_to.bold = run_from.bold
run_to.italic = run_from.italic
run_to.underline = run_from.underline
run_to.font.size = run_from.font.size
run_to.font.color.rgb = run_from.font.color.rgb
run_to.font.name = run_from.font.name
run_to.font.all_caps = run_from.font.all_caps
run_to.font.strike = run_from.font.strike
run_to.font.shadow = run_from.font.shadow
該函數(shù)實現(xiàn)了對段落內(nèi)文本樣式的完整復(fù)制,覆蓋了常見的 10+ 種格式屬性。
2. 分頁符識別機制
def is_page_break(element):
"""判斷元素是否為分頁符"""
if element.tag.endswith('p'):
for child in element:
if child.tag.endswith('br') and child.get(qn('type')) == 'page':
return True
elif element.tag.endswith('tbl'):
if element.getnext() is not None:
next_element = element.getnext()
if next_element.tag.endswith('p'):
for child in next_element:
if child.tag.endswith('br') and child.get(qn('type')) == 'page':
return True
return False
通過 XML 元素解析,實現(xiàn)了對段落和表格后分頁符的智能識別。
3. 表格深度克隆
def clone_table(old_table, new_doc):
"""根據(jù)舊表格創(chuàng)建新表格"""
new_table = new_doc.add_table(rows=len(old_table.rows), cols=len(old_table.columns))
if old_table.style:
new_table.style = old_table.style
for i, old_row in enumerate(old_table.rows):
for j, old_cell in enumerate(old_row.cells):
new_cell = new_table.cell(i, j)
for paragraph in new_cell.paragraphs:
new_cell._element.remove(paragraph._element)
for old_paragraph in old_cell.paragraphs:
new_paragraph = new_cell.add_paragraph()
for old_run in old_paragraph.runs:
new_run = new_paragraph.add_run(old_run.text)
copy_paragraph_style(old_run, new_run)
new_paragraph.alignment = old_paragraph.alignment
copy_cell_borders(old_cell, new_cell)
for i, col in enumerate(old_table.columns):
if col.width is not None:
new_table.columns[i].width = col.width
return new_table
該函數(shù)實現(xiàn)了:
- 表格樣式繼承
- 單元格內(nèi)容深度復(fù)制
- 邊框格式遷移
- 列寬精確復(fù)制
4. 主函數(shù)邏輯
def clone_document(old_doc_path, new_doc_path):
try:
old_doc = Document(old_doc_path)
new_doc = Document()
# 分頁符處理邏輯
elements = old_doc.element.body
para_index = 0
table_index = 0
index = 0
while index < len(elements):
element = elements[index]
if element.tag.endswith('p'):
old_para = old_doc.paragraphs[para_index]
clone_paragraph(old_para, new_doc)
para_index += 1
index += 1
elif element.tag.endswith('tbl'):
old_table = old_doc.tables[table_index]
clone_table(old_table, new_doc)
table_index += 1
index += 1
elif element.tag.endswith('br') and element.get(qn('type')) == 'page':
if index>0:
new_doc.add_paragraph().add_run().add_break(WD_BREAK.PAGE)
index += 1
else:
index += 1
# 檢查分頁符
if index < len(elements) and is_page_break(elements[index]):
if index>0:
new_doc.add_paragraph().add_run().add_break(WD_BREAK.PAGE)
index += 1
new_doc.save(new_doc_path)
print(f"文檔已成功保存至:{new_doc_path}")
except Exception as e:
print(f"復(fù)制文檔時發(fā)生錯誤:{e}")
主函數(shù)采用雙指針策略,同時維護段落和表格的索引計數(shù)器,確保元素順序的準確性。
使用示例
if __name__ == "__main__":
clone_document('1.docx', 'cloned_example.docx')
運行方式:
- 安裝依賴:
pip install python-docx - 準備源文件
1.docx - 執(zhí)行腳本生成克隆文件
注意事項
- 分節(jié)符支持:當前版本暫未實現(xiàn)分節(jié)符和頁眉頁腳的克?。ùa中已注釋相關(guān)部分)
- 兼容性測試:建議使用
.docx格式文件,.doc文件可能無法正確解析 - 性能優(yōu)化:處理大型文檔時建議增加內(nèi)存優(yōu)化邏輯
總結(jié)
本方案通過深度解析 Word 文檔的 XML 結(jié)構(gòu),實現(xiàn)了完整的樣式和格式遷移。后續(xù)可擴展方向:
- 支持分節(jié)符和頁眉頁腳克隆
- 增加圖片和圖表復(fù)制功能
- 開發(fā)圖形化操作界面
完整代碼已通過測試,可直接應(yīng)用于文檔自動化處理場景。通過適當擴展,可以構(gòu)建完整的文檔模板管理系統(tǒng)。
from docx import Document
from docx.shared import Pt, RGBColor
from docx.enum.text import WD_PARAGRAPH_ALIGNMENT, WD_BREAK
from docx.oxml import OxmlElement
from docx.oxml.shared import qn
def copy_paragraph_style(run_from, run_to):
"""復(fù)制 run 的樣式"""
run_to.bold = run_from.bold
run_to.italic = run_from.italic
run_to.underline = run_from.underline
run_to.font.size = run_from.font.size
run_to.font.color.rgb = run_from.font.color.rgb
run_to.font.name = run_from.font.name
run_to.font.all_caps = run_from.font.all_caps
run_to.font.strike = run_from.font.strike
run_to.font.shadow = run_from.font.shadow
def is_page_break(element):
"""判斷元素是否為分頁符(段落或表格后)"""
if element.tag.endswith('p'):
for child in element:
if child.tag.endswith('br') and child.get(qn('type')) == 'page':
return True
elif element.tag.endswith('tbl'):
# 表格后可能有分頁符(通過下一個元素判斷)
if element.getnext() is not None:
next_element = element.getnext()
if next_element.tag.endswith('p'):
for child in next_element:
if child.tag.endswith('br') and child.get(qn('type')) == 'page':
return True
return False
def clone_paragraph(old_para, new_doc):
"""根據(jù)舊段落創(chuàng)建新段落"""
new_para = new_doc.add_paragraph()
if old_para.style:
new_para.style = old_para.style
for old_run in old_para.runs:
new_run = new_para.add_run(old_run.text)
copy_paragraph_style(old_run, new_run)
new_para.alignment = old_para.alignment
return new_para
def copy_cell_borders(old_cell, new_cell):
"""復(fù)制單元格的邊框樣式"""
old_tc = old_cell._tc
new_tc = new_cell._tc
old_borders = old_tc.xpath('.//w:tcBorders')
if old_borders:
old_border = old_borders[0]
new_border = OxmlElement('w:tcBorders')
border_types = ['top', 'left', 'bottom', 'right', 'insideH', 'insideV']
for border_type in border_types:
old_element = old_border.find(f'.//w:{border_type}', namespaces={
'w': 'http://schemas.openxmlformats.org/wordprocessingml/2006/main'
})
if old_element is not None:
new_element = OxmlElement(f'w:{border_type}')
for attr, value in old_element.attrib.items():
new_element.set(attr, value)
new_border.append(new_element)
tc_pr = new_tc.get_or_add_tcPr()
tc_pr.append(new_border)
def clone_table(old_table, new_doc):
"""根據(jù)舊表格創(chuàng)建新表格"""
new_table = new_doc.add_table(rows=len(old_table.rows), cols=len(old_table.columns))
if old_table.style:
new_table.style = old_table.style
for i, old_row in enumerate(old_table.rows):
for j, old_cell in enumerate(old_row.cells):
new_cell = new_table.cell(i, j)
for paragraph in new_cell.paragraphs:
new_cell._element.remove(paragraph._element)
for old_paragraph in old_cell.paragraphs:
new_paragraph = new_cell.add_paragraph()
for old_run in old_paragraph.runs:
new_run = new_paragraph.add_run(old_run.text)
copy_paragraph_style(old_run, new_run)
new_paragraph.alignment = old_paragraph.alignment
copy_cell_borders(old_cell, new_cell)
for i, col in enumerate(old_table.columns):
if col.width is not None:
new_table.columns[i].width = col.width
return new_table
def clone_document(old_doc_path, new_doc_path):
try:
old_doc = Document(old_doc_path)
new_doc = Document()
# # 復(fù)制分節(jié)符及頁眉頁腳
# for old_section in old_doc.sections:
# new_section = new_doc.add_section(start_type=old_section.start_type)
# new_section.left_margin = old_section.left_margin
# new_section.right_margin = old_section.right_margin
# # 其他分節(jié)符屬性...
#
# # 頁眉
# for para in old_section.header.paragraphs:
# new_para = new_section.header.add_paragraph()
# for run in para.runs:
# new_run = new_para.add_run(run.text)
# copy_paragraph_style(run, new_run)
# new_para.alignment = para.alignment
#
# # 頁腳
# for para in old_section.footer.paragraphs:
# new_para = new_section.footer.add_paragraph()
# for run in para.runs:
# new_run = new_para.add_run(run.text)
# copy_paragraph_style(run, new_run)
# new_para.alignment = para.alignment
# 復(fù)制主體內(nèi)容
elements = old_doc.element.body
para_index = 0
table_index = 0
index = 0
while index < len(elements):
element = elements[index]
if element.tag.endswith('p'):
old_para = old_doc.paragraphs[para_index]
clone_paragraph(old_para, new_doc)
para_index += 1
index += 1
elif element.tag.endswith('tbl'):
old_table = old_doc.tables[table_index]
clone_table(old_table, new_doc)
table_index += 1
index += 1
elif element.tag.endswith('br') and element.get(qn('type')) == 'page':
if index>0:
new_doc.add_paragraph().add_run().add_break(WD_BREAK.PAGE)
index += 1
else:
index += 1
# 檢查分頁符
if index < len(elements) and is_page_break(elements[index]):
if index>0:
new_doc.add_paragraph().add_run().add_break(WD_BREAK.PAGE)
index += 1
new_doc.save(new_doc_path)
print(f"文檔已成功保存至:{new_doc_path}")
except Exception as e:
print(f"復(fù)制文檔時發(fā)生錯誤:{e}")
# 使用示例
if __name__ == "__main__":
clone_document('1.docx', 'cloned_example.docx')
到此這篇關(guān)于使用Python實現(xiàn)Word文檔的深度克隆的完整代碼的文章就介紹到這了,更多相關(guān)Python Word深度克隆內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Python使用描述符實現(xiàn)屬性類型檢查的案例解析
這篇文章主要介紹了Python使用描述符實現(xiàn)屬性類型檢查,實例屬性就是在一個類中將另一個類的實例作為該類的一個數(shù)屬性,本文通過代碼演示給大家介紹的非常詳細,需要的朋友可以參考下2022-05-05
Python requests.post()返回406錯誤的常見原因及解決方案
這篇文章主要介紹了Python requests.post()出現(xiàn)HTTP 406錯誤的原因,指出服務(wù)器無法匹配客戶端Accept頭要求,解決方案包括檢查請求頭、數(shù)據(jù)格式、User-Agent、認證信息及服務(wù)器限制,并建議通過調(diào)試重定向參數(shù)排查問題,需要的朋友可以參考下2025-07-07
python神經(jīng)網(wǎng)絡(luò)Keras搭建RFBnet目標檢測平臺
這篇文章主要為大家介紹了python神經(jīng)網(wǎng)絡(luò)Keras搭建RFBnet目標檢測平臺,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2022-05-05
關(guān)于Python函數(shù)參數(shù)的進階用法
這篇文章主要給大家分享的是Python函數(shù)參數(shù)的進階用法,Python函數(shù)的參數(shù)根據(jù)函數(shù) 在調(diào)用時 傳參的形式分為關(guān)鍵字參數(shù)和位置參數(shù),下面文章小編就來介紹相關(guān)資料,需要的朋友可以參考一下2021-10-10
python實現(xiàn)支持目錄FTP上傳下載文件的方法
這篇文章主要介紹了python實現(xiàn)支持目錄FTP上傳下載文件的方法,適用于windows及Linux平臺FTP傳輸文件及文件夾,需要的朋友可以參考下2015-06-06
深入理解Python中pywin32庫實現(xiàn)Windows自動化與系統(tǒng)交互
pywin32是一個讓?Python?能夠直接調(diào)用?Windows?API?和?COM?對象的擴展庫,本文將帶大家從入門到精通,系統(tǒng)性地理解?pywin32?的核心功能、內(nèi)部機制、典型應(yīng)用場景和高級用法2025-10-10

