Python使用Python-docx庫實現(xiàn)Word文檔自動化
一、引言
在日常辦公中,Word文檔處理是高頻需求。無論是生成報告、合同,還是批量修改文檔內(nèi)容,手動操作效率低下且易出錯。Python-docx作為Python生態(tài)中處理.docx文件的王牌庫,提供了從文檔創(chuàng)建、內(nèi)容編輯到格式控制的完整解決方案。本文將帶您全面掌握該庫的核心功能,并附實戰(zhàn)代碼示例。
注意:僅支持.docx格式(Office 2007及以上版本)。
Document對象相當于一篇文檔,由paragraph對象組成。
每個paragraph對象由run對象組成,有一些諸如字體之類的character-level的細節(jié)配置需要用run對象來操作。paragraph就是段落,run是一組格式相同的內(nèi)容,就是如果格式不一樣就要切換run了。
python-docx庫挺難用的,但是我咋感覺Python上操作Word文檔的只有這一個選項呢,也沒得選。
二、安裝與環(huán)境配置
通過pip一鍵安裝:
pip install python-docx
驗證安裝:
import docx print(docx.__version__) # 輸出當前版本,如0.8.11
三、基礎(chǔ)操作
創(chuàng)建文檔
1. 創(chuàng)建文檔對象
from docx import Document doc = Document() # 新建空白文檔
2. 標題與段落
• 標題:支持1-9級標題(level參數(shù)控制層級)
doc.add_heading('Python-docx實戰(zhàn)指南', level=0) # 主標題
doc.add_heading('第一章:基礎(chǔ)操作', level=1)
• 段落:支持普通文本、換行符及段落樣式
para = doc.add_paragraph('這是一個普通段落。')
para.add_run('加粗文本').bold = True # 追加帶格式的文本
更多操作可參考:
# * 向document末尾添加一個段落(返回的是最后的添加的這個段落對象的引用)
paragraph = document.add_paragraph('Lorem ipsum dolor sit amet.')
# * 還可以在這個段落之前添加段落:
prior_paragraph = paragraph.insert_paragraph_before('Lorem ipsum')
# * 下面是如何設置段落的樣式
document.add_paragraph('Lorem ipsum dolor sit amet.', style='ListBullet')
# * 或這
paragraph = document.add_paragraph('Lorem ipsum dolor sit amet.')
paragraph.style = 'List Bullet'
# * 上面是block-level的樣式(比如縮進)
# * 下面是Character-level的樣式(用add_run來設置)
paragraph = document.add_paragraph('Lorem ipsum ')
paragraph.add_run('dolor sit amet.')
paragraph = document.add_paragraph('Lorem ipsum ')
run = paragraph.add_run('dolor')
run.bold = True
paragraph.add_run(' sit amet.')
paragraph.add_run('dolor').bold = True
# * 等同于:
run = paragraph.add_run('dolor')
run.bold = True
paragraph = document.add_paragraph()
paragraph.add_run('Lorem ipsum ')
paragraph.add_run('dolor').bold = True
paragraph.add_run(' sit amet.')
3. 保存文檔
doc.save('demo.docx') # 保存至當前目錄
讀取文檔
from docx import Document
# 打開文檔
doc = Document('example.docx')
# 遍歷段落
for para in doc.paragraphs:
print(para.text)
# 遍歷表格
for table in doc.tables:
for row in table.rows:
for cell in row.cells:
print(cell.text)
1. 打開文檔的三種寫法
寫法1:
document = Document('existing-document-file.docx')
寫法2:
f = open('foobar.docx', 'rb')
document = Document(f)
f.close()
寫法3(帶保存文檔):
with open('foobar.docx', 'rb') as f:
source_stream = StringIO(f.read())
document = Document(source_stream)
source_stream.close()
target_stream = StringIO()
document.save(target_stream)
四、進階功能:玩轉(zhuǎn)復雜結(jié)構(gòu)
表格操作
表格是一個table對象,里面每一個單元格是一個cell,里面呈現(xiàn)的內(nèi)容是一堆paragraph。所以表格里的字體的細微設置也可以通過這些paragraph和里面的run來實現(xiàn)。
自動生成數(shù)據(jù)表格并設置樣式:
table = document.add_table(rows=3, cols=3) # 創(chuàng)建3x3表格
table.style = 'LightShading-Accent1' # 應用預定義樣式
# 獲取第一行第二列的單元格,并修改單元格內(nèi)容
cell = table.cell(0, 1)
cell.text = 'parrot, possibly dead'
# 獲取第一行,并修改單元格內(nèi)容
row = table.rows[1]
row.cells[0].text = 'Foo bar to you.'
row.cells[1].text = 'And a hearty foo bar to you too sir!'
# 獲取單元格的行列數(shù)
row_count = len(table.rows)
col_count = len(table.columns)
row = table.add_row()
# 添加表格數(shù)據(jù)
items = (
(7, '1024', 'Plush kittens'),
(3, '2042', 'Furbees'),
(1, '1288', 'French Poodle Collars, Deluxe'),
)
# 下面是添加一個1行3列的表格
table = document.add_table(1, 3)
# 修改表格中第一行的數(shù)據(jù)
heading_cells = table.rows[0].cells
heading_cells[0].text = 'Qty'
heading_cells[1].text = 'SKU'
heading_cells[2].text = 'Description'
# 一行一行添加數(shù)據(jù)
for item in items:
cells = table.add_row().cells
cells[0].text = str(item[0])
cells[1].text = item[1]
cells[2].text = item[2]
# 另一種填充數(shù)據(jù)方法
table.cell(0, 0).text = '單元格 1,1'
table.cell(0, 1).text = '單元格 1,2'
table.cell(1, 0).text = '單元格 2,1'
table.cell(1, 1).text = '單元格 2,2'
# 表格數(shù)據(jù)也可以這么遍歷和批量填充
for row in table.rows:
for cell in row.cells:
cell.text = "數(shù)據(jù)單元"
# 合并單元格示例
table.cell(0,0).merge(table.cell(1,1)) # 跨行列合并
1. 對指定單元格設置邊框線
函數(shù):
from docx.oxml import OxmlElement
from docx.oxml.ns import qn
def set_cell_border(cell, **kwargs):
"""
Set cell`s border
Usage:
set_cell_border(
cell,
top={"sz": 12, "val": "single", "color": "#FF0000", "space": "0"},
bottom={"sz": 12, "color": "#00FF00", "val": "single"},
left={"sz": 24, "val": "dashed", "shadow": "true"},
right={"sz": 12, "val": "dashed"},
)
"""
tc = cell._tc
tcPr = tc.get_or_add_tcPr()
# check for tag existnace, if none found, then create one
tcBorders = tcPr.first_child_found_in("w:tcBorders")
if tcBorders is None:
tcBorders = OxmlElement('w:tcBorders')
tcPr.append(tcBorders)
# list over all available tags
for edge in ('left', 'top', 'right', 'bottom', 'insideH', 'insideV'):
edge_data = kwargs.get(edge)
if edge_data:
tag = 'w:{}'.format(edge)
# check for tag existnace, if none found, then create one
element = tcBorders.find(qn(tag))
if element is None:
element = OxmlElement(tag)
tcBorders.append(element)
# looks like order of attributes is important
for key in ["sz", "val", "color", "space", "shadow"]:
if key in edge_data:
element.set(qn('w:{}'.format(key)), str(edge_data[key]))
使用示例:
table = document.add_table(rows=1, cols=3)
hdr_cells = table.rows[0].cells
hdr_cells[0].text = 'Qty'
set_cell_border(
hdr_cells[0],
top={"sz": 4, "val": "single", "color": "#000000", "space": "0"},
bottom={"sz": 4, "val": "single", "color": "#000000", "space": "0"},
left={"sz": 4, "val": "single", "color": "#000000", "space": "0"},
right={"sz": 4, "val": "single", "color": "#000000", "space": "0"},
)
2. table.style
Table Grid:這個就是標準的邊框線全都顯現(xiàn)的表格
3. 表格尺寸的設置
- 寬度自適應:
table.autofit = True - 設置一行的行高:
from docx.shared import Cm table.rows[0].height = Cm(0.93)
4. 表格級別的字體設置
from docx.shared import Pt table.style.font.size = Pt(12) table.style.font.name = "Times New Roman"
(經(jīng)測試好像中文字體設置了也沒用,所以我的個人建議是要么通過run來單獨設置,要么直接設置全document的字體,見本節(jié)第四小節(jié)“字體和段落樣式”第二小節(jié)“document級別設置字體”)
5. 表格位置設置
居中:
from docx.enum.table import WD_TABLE_ALIGNMENT table.alignment = WD_TABLE_ALIGNMENT.CENTER`
6. 設置表格中的文字垂直、水平對齊
這個我只找到逐cell來設置的代碼:
from docx.enum.text import WD_ALIGN_PARAGRAPH from docx.enum.table import WD_ALIGN_VERTICAL cell.paragraphs[0].paragraph_format.alignment = WD_ALIGN_PARAGRAPH.CENTER cell.vertical_alignment = WD_ALIGN_VERTICAL.CENTER
7. 復制表格
以復制第一個表格為例:
from copy import deepcopy table = deepcopy(doc.tables[0]) para1 = doc.add_paragraph() para1._p.addnext(table._element)
8. 增刪行
增加行:
table.add_row()
刪除行(以刪除最后一行為例):
def remove_row(table, row):
tbl = table._tbl
tr = row._tr
tbl.remove(tr)
row = table.rows[len(table.rows) - 1]
remove_row(table, row)
圖片
支持調(diào)整尺寸(單位英寸或厘米)
from docx.shared import Inches
doc.add_picture('logo.png', width=Inches(2.5), height=Inches(2)) # 指定寬高
分頁符
控制文檔結(jié)構(gòu)
寫法一:
doc.add_page_break() # 強制分頁
寫法二:
doc.paragraphs[-1].add_run().add_break(WD_BREAK.PAGE)
字體和段落樣式
1. run級別設置字體格式
顏色、大小、加粗、斜體、下劃線、上標下標
from docx.shared import RGBColor, Pt
run = para.add_run('紅色斜體文本')
run.font.color.rgb = RGBColor(255,0,0) # 設置紅色
run.font.size = Pt(14) # 字號14磅
run.bold = True #加粗
run.italic = True # 斜體
run.underline = True
run2=para.add_run("1")
run2.font.subscript = True # 下標
run3=para.add_run("2")
run3.font.superscript = True # 上標
2. document級別設置字體格式
大小、字體
from docx.shared import Pt
from docx.oxml.ns import qn
document.styles["Normal"].font.size = Pt(12)
document.styles['Normal'].font.name = 'Times New Roman'
document.styles['Normal']._element.rPr.rFonts.set(qn('w:eastAsia'), '宋體')
3. paragraph級別
1. 設置段落格式
縮進、間距、對齊
from docx.enum.text import WD_ALIGN_PARAGRAPH para_format = para.paragraph_format para_format.alignment = WD_ALIGN_PARAGRAPH.CENTER # 居中對齊 para_format.line_spacing = Pt(18) # 行間距
2. 設置字體格式
字號
from docx.shared import Pt para1.style.font.size = Pt(12)
4. 字號對應關(guān)系
小四 - Pt(12)
5. 自定義段落/字符格式
自定義格式:
# 創(chuàng)建自定義段落樣式(第一個參數(shù)為樣式名, 第二個參數(shù)為樣式類型, 1為段落樣式, 2為字符樣式, 3為表格樣式)
UserStyle1 = document.styles.add_style('UserStyle1', 1)
# 設置字體尺寸
UserStyle1.font.size = Pt(40)
# 設置字體顏色
UserStyle1.font.color.rgb = RGBColor(0xff, 0xde, 0x00)
# 居中文本
UserStyle1.paragraph_format.alignment = WD_ALIGN_PARAGRAPH.CENTER
# 設置中文字體
UserStyle1.font.name = '微軟雅黑'
UserStyle1._element.rPr.rFonts.set(qn('w:eastAsia'), '微軟雅黑')
使用格式:
# 使用自定義段落樣式
document.add_paragraph('自定義段落樣式', style = UserStyle1)
# 使用自定義字符樣式
document.add_paragraph('').add_run('正月里采花無喲花采', style = UserStyle2)
超鏈接
from docx.oxml import OxmlElement
from docx.oxml.ns import qn
def add_hyperlink(paragraph, url, text):
# 創(chuàng)建超鏈接元素
part = paragraph.part
r_id = part.relate_to(url, "http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink", is_external=True)
hyperlink = OxmlElement('w:hyperlink')
hyperlink.set(qn('r:id'), r_id)
# 創(chuàng)建文字元素
run = OxmlElement('w:r')
run_text = OxmlElement('w:t')
run_text.text = text
run.append(run_text)
hyperlink.append(run)
# 添加到段落中
paragraph._p.append(hyperlink)
doc = Document()
p = doc.add_paragraph('點擊訪問: ')
add_hyperlink(p, 'https://www.example.com', '示例鏈接')
doc.save('hyperlink.docx')
分欄
from docx import Document
from docx.oxml import OxmlElement
from docx.oxml.ns import qn
document = Document()
section = document.sections[0]
# * 設置欄目數(shù)為2
sectPr = section._sectPr
cols = sectPr.xpath('./w:cols')[0]
cols.set(qn('w:num'),'2')
document.save('demo.docx')
# * 下面是對每個欄目進行格式設置
from docx import Document from docx.shared import Cm, Pt
document = Document()
sections = document.sections
for section in sections:
section.start_type = 1 # 設置起始頁為奇數(shù)
section.orientation = 0 # 設置頁面方向為縱向
section.page_width = Cm(21) # 設置頁面寬度
section.page_height = Cm(29.7) # 設置頁面高度
section.left_margin = Cm(2) # 設置左邊距
section.right_margin = Cm(2) # 設置右邊距
section.top_margin = Cm(2) # 設置上邊距
section.bottom_margin = Cm(2) # 設置下邊距
section.gutter = Cm(0.5) # 設置分欄之間的間隔
section.cols_num = 2 # 設置分欄數(shù)
設置頁眉頁腳
# ****************設置普通頁眉*********
doc = Document('existing-document-file.docx')
doc.sections[0].header.paragraphs[0].text = "這是第1節(jié)頁眉"
doc.save('existing-document-file.docx')
# ****************設置奇偶頁眉*********
doc = Document('existing-document-file.docx')
doc.settings.odd_and_even_pages_header_footer = True
doc.sections[0].even_page_header.paragraphs[0].text = "這是偶數(shù)頁頁眉"
doc.sections[0].header.paragraphs[0].text = "這是奇數(shù)頁頁眉"
doc.save('existing-document-file.docx')
# ****************設置奇偶頁眉*********
doc = Document('existing-document-file.docx')
doc.sections[0].different_first_page_header_footer = True
doc.sections[0].first_page_header.paragraphs[0].text = "這是首頁頁眉"
doc.save('existing-document-file.docx')
插入文本框
from docx import Document
doc = Document()
from docx.shared import Inches
width = Inches(1.0) # 設置文本框?qū)挾?
height = Inches(4.0) # 設置文本框高度
# 插入文本框
text_box = doc.add_textbox(width, height)
from docx.shared import Pt
from docx.enum.text import WD_ALIGN_VERTICAL
# 在文本框中添加一個段落
paragraph = text_box.add_paragraph()
# 設置文本方向為豎排
paragraph.alignment = WD_ALIGN_VERTICAL.ORIENT_90
# 添加豎排文本
text = "豎排文本"
run = paragraph.add_run(text)
# 設置文本樣式,例如字體大小和顏色
font = run.font
font.size = Pt(12) # 設置字體大小
font.color.rgb = (0x00, 0x00, 0x00) # 設置字體顏色(這里是黑色)
doc.save("vertical_text.docx")
插入目錄
from docx.oxml.ns import qn
from docx.oxml import OxmlElement
paragraph = self.document.add_paragraph()
run = paragraph.add_run()
fldChar = OxmlElement('w:fldChar') # creates a new element
fldChar.set(qn('w:fldCharType'), 'begin') # sets attribute on element
instrText = OxmlElement('w:instrText')
instrText.set(qn('xml:space'), 'preserve') # sets attribute on element
instrText.text = 'TOC \o "1-3" \h \z \u' # change 1-3 depending on heading levels you need
fldChar2 = OxmlElement('w:fldChar')
fldChar2.set(qn('w:fldCharType'), 'separate')
fldChar3 = OxmlElement('w:t')
fldChar3.text = "Right-click to update field."
fldChar2.append(fldChar3)
fldChar4 = OxmlElement('w:fldChar')
fldChar4.set(qn('w:fldCharType'), 'end')
r_element = run._r
r_element.append(fldChar)
r_element.append(instrText)
r_element.append(fldChar2)
r_element.append(fldChar4)
p_element = paragraph._p
# 下面是自動更新目錄
import lxml
import os
from docx import Document
# 設置待自動更新目錄的文件
file_name = "test.docx"
# 讀取文件,初始化為document對象
word_obj = Document(os.path.realpath(file_name))
# 初始化各項參數(shù)
name_space = "{http://schemas.openxmlformats.org/wordprocessingml/2006/main}"
update_name_space = "%supdateFields" % name_space
val_name_space = "%sval" % name_space
# 自動更新目錄
try:
element_update_field_obj = lxml.etree.SubElement(word_obj.settings.element, update_name_space)
element_update_field_obj.set(val_name_space, "true")
except Exception as e:
del e
# 保存更新后的word文件對象
word_obj.save(os.path.realpath(file_name))
插入列表
有序列表:
document.add_paragraph('把冰箱門打開', style='List Number')
document.add_paragraph('把大象裝進去', style='List Number')
document.add_paragraph('把冰箱門關(guān)上', style='List Number')
無序列表:
document.add_paragraph('天地匆匆', style='List Bullet')
document.add_paragraph('遑遑無歸', style='List Bullet')
document.add_paragraph('引勢而流', style='List Bullet')
document.add_paragraph('乾震坎艮', style='List Bullet')
五、API
1. Document.add_paragraph()
入?yún)ⅲ?/p>
- style:如
'Heading 1'
六、實戰(zhàn)應用場景
1. 自動化報告生成
結(jié)合數(shù)據(jù)源(如Excel/Pandas),動態(tài)填充表格和圖表,生成周報/月報。
2. 簡歷批量生成
通過模板替換變量(姓名、教育背景等),快速生成千人級個性化簡歷。
def create_resume(data):
doc = Document()
doc.add_heading(data['name'], level=1)
# 動態(tài)填充教育、工作經(jīng)驗等模塊...
return doc.save(f"{data['name']}_簡歷.docx")
3. 合同模板化處理
預設條款庫,根據(jù)業(yè)務需求組合生成標準化合同。
七、注意事項與擴展
- 兼容性:部分復雜格式(如VBA宏)需結(jié)合
pywin32庫操作原生Word。 - 性能優(yōu)化:處理超大型文檔時,建議分塊讀寫。
- 生態(tài)整合:
• docxtpl:基于模板引擎動態(tài)渲染內(nèi)容
• pandas:結(jié)合數(shù)據(jù)分析生成圖表報告
八、常見問題及其解決方案
KeyError: "no style with name 'Table Grid'":這個是在add_table()參數(shù)里設置style="Table Grid"時出現(xiàn)的,這個是由于Word版本不同導致的,解決方案是在比較新的Word版本里在表設計這里把第一個表格樣式(Table Grid就是這個)設為默認值,重新渲染就可以了:

九、總結(jié)
Python-docx以其簡潔的API和強大的功能,成為辦公自動化領(lǐng)域的核心工具。通過本文的學習,讀者可實現(xiàn)從簡單文本操作到復雜文檔生成的跨越。
以上就是Python使用Python-docx庫實現(xiàn)Word文檔自動化的詳細內(nèi)容,更多關(guān)于Python-docx Word文檔自動化的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
使用Python將PDF文件轉(zhuǎn)存為圖片的代碼示例
因工作中的某些奇葩要求,需要將PDF文件的每頁內(nèi)容轉(zhuǎn)存成按順序編號的圖片,用第三方軟件或者在線轉(zhuǎn)換也可以,但批量操作還是Python方便,所以本文給大家介紹了使用Python將PDF文件轉(zhuǎn)存為圖片的方法,需要的朋友可以參考下2023-09-09
輕松掌握python的dataclass讓你的代碼更簡潔優(yōu)雅
本文總結(jié)了幾個我在使用Python的dataclass時常用的技巧,dataclass裝飾器可以幫助我們簡化數(shù)據(jù)類的定義過程,包括設置默認值、隱藏敏感信息、設置只讀對象以及將其轉(zhuǎn)化為元組和字典,通過使用dataclass,我們可以更高效地進行數(shù)據(jù)分析和處理,感興趣的朋友跟隨小編一起看看吧2025-01-01
CentOS 6.5中安裝Python 3.6.2的方法步驟
centos 6.5默認自帶的python版本為2.6,而下面這篇文章主要給大家介紹了關(guān)于在CentOS 6.5中安裝Python 3.6.2的方法步驟,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧。2017-12-12
Python基于ssh遠程連接Mysql數(shù)據(jù)庫操作
這篇文章主要為大家介紹了Python基于ssh遠程連接Mysql數(shù)據(jù)庫操作示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2022-06-06
Python使用htpasswd實現(xiàn)基本認證授權(quán)的例子
這篇文章主要介紹了Python使用htpasswd實現(xiàn)基本認證授權(quán)的例子,服務器使用的是mini_httpd,需要的朋友可以參考下2014-06-06

