Python使用python-docx庫復制Word文檔樣式的實現(xiàn)方法
引言
在日常辦公中,我們經(jīng)常需要處理Word文檔的格式調(diào)整、內(nèi)容更新等任務。對于那些希望通過編程手段自動完成這些工作的開發(fā)者來說,Python及其豐富的第三方庫提供了強大的支持。本文將介紹如何使用python-docx庫來復制一個Word文檔的內(nèi)容及樣式,并展示如何利用此方法進行文檔內(nèi)容的自動化處理。
環(huán)境準備
首先,確保你已經(jīng)安裝了python-docx庫。如果尚未安裝,可以通過以下命令進行安裝:
pip install python-docx
主要功能實現(xiàn)
復制段落和文本框樣式:通過定義
copy_paragraph_style
函數(shù),我們可以復制舊段落或文本框的樣式到新創(chuàng)建的段落或文本框上。識別分頁符:
is_page_break
函數(shù)幫助我們在文檔元素之間識別是否含有分頁符,這對于保持文檔布局的一致性非常重要。克隆段落和表格:通過
clone_paragraph
和clone_table
函數(shù),我們可以根據(jù)舊文檔中的段落或表格創(chuàng)建新的段落或表格,并且保留原有的樣式設置。復制單元格邊框:為了使新生成的表格看起來與原表格一致,我們實現(xiàn)了
copy_cell_borders
函數(shù)來復制每個單元格的邊框樣式。完整文檔復制:最后,通過
clone_document
函數(shù),我們可以復制整個文檔的內(nèi)容和樣式到一個新的Word文檔中。
示例代碼
以下是簡化版的核心代碼示例,展示了如何從舊文檔中提取內(nèi)容并創(chuàng)建一個新的文檔:
from docx import Document # 假設其他必需的導入已包含在此處 def clone_document(old_doc_path, new_doc_path, out_text_list): try: # 加載舊文檔和創(chuàng)建新文檔 old_doc = Document(old_doc_path) new_doc = Document() # 復制主體內(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'): # 處理段落... para_index += 1 elif element.tag.endswith('tbl'): # 處理表格... table_index += 1 index += 1 # 保存新文檔 new_doc.save(new_doc_path) print(f"文檔已成功保存至:{new_doc_path}") except Exception as e: print(f"復制文檔時發(fā)生錯誤:{e}")
結(jié)論
通過上述方法,我們可以高效地復制Word文檔的內(nèi)容和樣式,這為文檔處理自動化提供了一種有效的解決方案。當然,根據(jù)實際需求的不同,你可以進一步擴展和完善這個基礎框架,比如添加對更多樣式的支持、優(yōu)化性能等。
希望這篇文章能為你提供有價值的參考,幫助你在日常工作中更高效地處理Word文檔。
生成文件代碼
from docx import Document from docx.enum.text import WD_BREAK from docx.oxml import OxmlElement from docx.oxml.shared import qn from copy_word_only_text_json import clone_document as gen_to_list def copy_paragraph_style(run_from, run_to): """復制 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, out_text_list): """根據(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(out_text_list.pop(0)) copy_paragraph_style(old_run, new_run) new_para.alignment = old_para.alignment return new_para def copy_cell_borders(old_cell, new_cell): """復制單元格的邊框樣式""" 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, out_text_list): """根據(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(out_text_list.pop(0)) 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, out_text_list ): # global out_text_list try: old_doc = Document(old_doc_path) new_doc = Document() # # 復制分節(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 # 復制主體內(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, out_text_list) para_index += 1 index += 1 elif element.tag.endswith('tbl'): old_table = old_doc.tables[table_index] clone_table(old_table, new_doc, out_text_list) 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 if new_doc_path: new_doc.save(new_doc_path) print(f"文檔已成功保存至:{new_doc_path}") else: return out_text_list except Exception as e: print(f"復制文檔時發(fā)生錯誤:{e}") # 使用示例 if __name__ == "__main__": out = gen_to_list('.docx', '') if out: print("文檔內(nèi)容:\n", out, """按照順序的文檔內(nèi)容請根據(jù)用戶要求更改文檔內(nèi)容,而不改變順序,且不改變內(nèi)容個數(shù),最后將內(nèi)容list 輸出為到給定的json中 ```json {"輸出":[]} ``` 用戶輸入:請潤色 """) print("請求llm") print("提取json") print("填入模版") out = clone_document('.docx', 'only_text.docx',out)
生成文本列表代碼
from docx import Document from docx.enum.text import WD_BREAK from docx.oxml import OxmlElement from docx.oxml.shared import qn def copy_paragraph_style(run_from, run_to): """復制 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,out_text_list): """根據(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: out_text_list.append(old_run.text) 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): """復制單元格的邊框樣式""" 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,out_text_list): """根據(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: out_text_list.append(old_run.text) 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): # global out_text_list out_text_list = [] try: old_doc = Document(old_doc_path) new_doc = Document() # # 復制分節(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 # 復制主體內(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,out_text_list) para_index += 1 index += 1 elif element.tag.endswith('tbl'): old_table = old_doc.tables[table_index] clone_table(old_table, new_doc,out_text_list) 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 if new_doc_path: new_doc.save(new_doc_path) print(f"文檔已成功保存至:{new_doc_path}") else: return out_text_list except Exception as e: print(f"復制文檔時發(fā)生錯誤:{e}") # 使用示例 if __name__ == "__main__": out=clone_document('南山三防工作專報.docx', '') if out: print("文檔內(nèi)容:\n",out,"""按照順序的文檔內(nèi)容請根據(jù)用戶要求更改文檔內(nèi)容,而不改變順序,且不改變內(nèi)容個數(shù),最后將內(nèi)容list 輸出為到給定的json中 ```json {"輸出":[]} ``` 用戶輸入:請潤色 """) print("請求llm") print("提取json") print("填入模版")
到此這篇關(guān)于Python使用python-docx庫復制Word文檔樣式的實現(xiàn)方法的文章就介紹到這了,更多相關(guān)Python python-docx庫復制Word樣式內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
詳解tensorflow載入數(shù)據(jù)的三種方式
這篇文章主要介紹了詳解tensorflow載入數(shù)據(jù)的三種方式,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-04-04python在windows下實現(xiàn)ping操作并接收返回信息的方法
這篇文章主要介紹了python在windows下實現(xiàn)ping操作并接收返回信息的方法,實例分析了Python實現(xiàn)ping操作的技巧,具有一定參考借鑒價值,需要的朋友可以參考下2015-03-03一文教會你用python連接并簡單操作SQLserver數(shù)據(jù)庫
最近要將數(shù)據(jù)寫到數(shù)據(jù)庫里,學習了一下如何用Python來操作SQLServer數(shù)據(jù)庫,下面這篇文章主要給大家介紹了關(guān)于用python連接并簡單操作SQLserver數(shù)據(jù)庫的相關(guān)資料,需要的朋友可以參考下2022-09-09Windows系統(tǒng)下安裝tensorflow的配置步驟
這篇文章主要介紹了Windows系統(tǒng)下安裝tensorflow,本文通過圖文并茂的形式給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2022-07-07Python Pycharm虛擬下百度飛漿PaddleX安裝報錯問題及處理方法(親測100%有效)
最近很多朋友給小編留言在安裝PaddleX的時候總是出現(xiàn)各種奇葩問題,不知道該怎么處理,今天小編通過本文給大家介紹下Python Pycharm虛擬下百度飛漿PaddleX安裝報錯問題及處理方法,真的有效,遇到同樣問題的朋友快來參考下吧2021-05-05