文章目录
一、引言
在日常办公中,Word文档处理是高频需求。无论是生成报告、合同,还是批量修改文档内容,手动操作效率低下且易出错。Python-docx作为Python生态中处理.docx文件的王牌库,提供了从文档创建、内容编辑到格式控制的完整解决方案。本文将带您全面掌握该库的核心功能,并附实战代码示例。
注意:仅支持.docx格式(Office 2007及以上版本)。
Document对象相当于一篇文档,由paragraph对象组成。
每个paragraph对象由run对象组成,有一些诸如字体之类的character-level的细节配置需要用run对象来操作,这个具体情况具体分析吧。
python-docx库挺难用的,但是我咋感觉Python上操作Word文档的只有这一个选项呢,也没得选。
二、安装与环境配置
通过pip一键安装:
pip install python-docx
验证安装:
import docx
print(docx.__version__) # 输出当前版本,如0.8.11
三、基础操作
1. 创建文档
1. 创建文档对象
from docx import Document
doc = Document() # 新建空白文档
2. 标题与段落
• 标题:支持1-9级标题(level参数控制层级)
doc.add_heading('Python-docx实战指南', level=0) # 主标题
doc.add_heading('第一章:基础操作', 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') # 保存至当前目录
2. 读取文档
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)
四、进阶功能:玩转复杂结构
1. 表格操作
自动生成数据表格并设置样式:
table = doc.add_table(rows=3, cols=3) # 创建3x3表格
table.style = 'LightShading-Accent1' # 应用预定义样式
# * 获取第一行第二列的单元格,并修改单元格内容
cell = table.cell(0, 1)
cell.text = 'parrot, possibly dead'
# * 获取第一行,并修改单元格内容
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!'
# * 打印每个单元格内容
for row in table.rows:
for cell in row.cells:
print(cell.text)
# * 获取单元格的行列数
row_count = len(table.rows)
col_count = len(table.columns)
row = table.add_row()
# * 添加表格数据
items = (
(7, '1024', 'Plush kittens'),
(3, '2042', 'Furbees'),
(1, '1288', 'French Poodle Collars, Deluxe'),
)
# 下面是添加一个1行3列的表格
table = document.add_table(1, 3)
# 修改表格中第一行的数据
heading_cells = table.rows[0].cells
heading_cells[0].text = 'Qty'
heading_cells[1].text = 'SKU'
heading_cells[2].text = 'Description'
# 为每个Item添加一行数据。
for item in items:
cells = table.add_row().cells
cells[0].text = str(item.qty)
cells[1].text = item.sku
cells[2].text = item.desc
# 填充数据方法
for row in table.rows:
for cell in row.cells:
cell.text = "数据单元"
# 填充数据方法
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'
# 合并单元格示例
table.cell(0,0).merge(table.cell(1,1)) # 跨行列合并
2. 图片
支持调整尺寸(单位英寸或厘米)
from docx.shared import Inches
doc.add_picture('logo.png', width=Inches(2.5), height=Inches(2)) # 指定宽高
3. 分页符
控制文档结构
写法一:
doc.add_page_break() # 强制分页
写法二:
doc.paragraphs[-1].add_run().add_break(WD_BREAK.PAGE)
4. 字体和段落样式
• 字体格式:颜色、大小、下划线
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.italic = True
run.underline = True
• 段落格式:缩进、间距、对齐
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) # 行间距
5. 超链接
from docx.oxml import OxmlElement
from docx.oxml.ns import qn
def add_hyperlink(paragraph, url, text):
# 创建超链接元素
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)
# 创建文字元素
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')
6. 分栏
from docx import Document
from docx.oxml import OxmlElement
from docx.oxml.ns import qn
document = Document()
section = document.sections[0]
# * 设置栏目数为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 # 设置起始页为奇数
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 # 设置分栏数
7. 设置页眉页脚
# ****************设置普通页眉*********
doc = Document('existing-document-file.docx')
doc.sections[0].header.paragraphs[0].text = "这是第1节页眉"
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 = "这是偶数页页眉"
doc.sections[0].header.paragraphs[0].text = "这是奇数页页眉"
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')
8. 插入文本框
from docx import Document
doc = Document()
from docx.shared import Inches
width = Inches(1.0) # 设置文本框宽度
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")
9. 插入目录
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))
# 初始化各项参数
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))
五、API
1. Document.add_paragraph()
入参:
- style:如
'Heading 1'
六、实战应用场景
1. 自动化报告生成
结合数据源(如Excel/Pandas),动态填充表格和图表,生成周报/月报。
2. 简历批量生成
通过模板替换变量(姓名、教育背景等),快速生成千人级个性化简历。
def create_resume(data):
doc = Document()
doc.add_heading(data['name'], level=1)
# 动态填充教育、工作经验等模块...
return doc.save(f"{data['name']}_简历.docx")
3. 合同模板化处理
预设条款库,根据业务需求组合生成标准化合同。
七、注意事项与扩展
- 兼容性:部分复杂格式(如VBA宏)需结合
pywin32
库操作原生Word。 - 性能优化:处理超大型文档时,建议分块读写。
- 生态整合:
• docxtpl:基于模板引擎动态渲染内容
• pandas:结合数据分析生成图表报告
八、总结
Python-docx以其简洁的API和强大的功能,成为办公自动化领域的核心工具。通过本文的学习,读者可实现从简单文本操作到复杂文档生成的跨越。立即动手实践,让代码解放你的双手!