深入解析Python-docx库:轻松玩转Word文档自动化

诸神缄默不语-个人技术博文与视频目录

一、引言

在日常办公中,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()

入参:

  1. 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. 合同模板化处理

预设条款库,根据业务需求组合生成标准化合同。

七、注意事项与扩展

  1. 兼容性:部分复杂格式(如VBA宏)需结合pywin32库操作原生Word。
  2. 性能优化:处理超大型文档时,建议分块读写。
  3. 生态整合
    docxtpl:基于模板引擎动态渲染内容
    pandas:结合数据分析生成图表报告

八、总结

Python-docx以其简洁的API和强大的功能,成为办公自动化领域的核心工具。通过本文的学习,读者可实现从简单文本操作到复杂文档生成的跨越。立即动手实践,让代码解放你的双手!

本文撰写过程中参考的其他网络资料

  1. Python读写word文档(.docx) python-docx的使用_python 读取docx-CSDN博客
  2. Python-docx库-常用操作篇-CSDN博客
  3. Python中的文档处理神器:深度解析python-docx库-CSDN博客
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

诸神缄默不语

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值