Python工具箱系列(四十七)

发布时间 2024-01-05 11:42:47作者: 西安衍舆航天

如何操作docx文档(上)
 

微软最近几年,积极投身开源运动,不仅购买了github震惊世界,还在自家操作操作系统上实现了WSL,与Linux实现了一家亲。除此之外,还将vscode开源,并且投放出了一项又一项的性价比极高的免费软件产品。之所以微软如此大手笔,原因之一就是微软的Office贡献了大把的现金,简直就是印钞机。

微软的Office以前使用专有格式,兼容性差。2002年Sun(后被Oracle收购)等公司组建了OASIS技术委员会,开始定义一种基于XML的开放标准文档格式:ODF标准。这份标准引发了全球政府的关注,推动了文档标准化的进程。微软随后也推出了自己的标准文档格式OpenXML,并从Office2007版开始正式支持。此后,巨头们展开了激烈的文档标准之争。OpenXML推出后,理论上其它第三方也能够开发相关处理软件。此外,OpenXML也是结合了XML与ZIP压缩技术,因此微软office系列各文档后缀都带上了X。如docx、xlsx、pptx等。下面使用标准库zipfile打开一个docx文档,代码如下所示。

import zipfile

def getdocxinfo(docxfilename):
    """
    获得docx的信息

    Args:
        docxfilename (string): word文档名
    """
    zipcontainer = zipfile.ZipFile(docxfilename, 'r', zipfile.ZIP_DEFLATED )
    
    # 详细输出
    for fileinfo in zipcontainer.infolist():
        print(fileinfo)
    
    zipcontainer.close()
        
getdocxinfo(r'd:\test\1.docx')

 

运行后能够看到输出结果如下所示。

<ZipInfo filename='[Content_Types].xml' compress_type=deflate file_size=1621 compress_size=396>
<ZipInfo filename='_rels/.rels' compress_type=deflate file_size=590 compress_size=239>
<ZipInfo filename='word/document.xml' compress_type=deflate file_size=211068 compress_size=20828>
<ZipInfo filename='word/_rels/document.xml.rels' compress_type=deflate file_size=2062 compress_size=363>
<ZipInfo filename='word/embeddings/Microsoft_Visio_Drawing.vsdx' file_size=90912>
<ZipInfo filename='word/media/image4.png' file_size=36037>
<ZipInfo filename='word/media/image5.png' file_size=42750>
<ZipInfo filename='word/media/image6.emf' compress_type=deflate file_size=628844 compress_size=146576>
<ZipInfo filename='word/embeddings/Microsoft_Visio_Drawing1.vsdx' file_size=180125>
<ZipInfo filename='word/theme/theme1.xml' compress_type=deflate file_size=8398 compress_size=1761>
<ZipInfo filename='word/settings.xml' compress_type=deflate file_size=3893 compress_size=1378>
<ZipInfo filename='word/numbering.xml' compress_type=deflate file_size=32940 compress_size=2266>
<ZipInfo filename='word/styles.xml' compress_type=deflate file_size=35148 compress_size=3992>
<ZipInfo filename='word/webSettings.xml' compress_type=deflate file_size=655 compress_size=295>
<ZipInfo filename='word/fontTable.xml' compress_type=deflate file_size=2821 compress_size=664>
<ZipInfo filename='docProps/core.xml' compress_type=deflate file_size=754 compress_size=371>
<ZipInfo filename='docProps/app.xml' compress_type=deflate file_size=717 compress_size=380>

从输出结果我们看到docx类似于zip,也是一个容器,包含了各类文档。在word/media目录下有图片,在word目录下有document.xml等直接可以使用文本编辑器打开,也就是WORD中显示的各项内容了。EXCEL与PPT的文档组织结构上也类似。

使用python来操控word文档,仍然是一个基于原文档/模板进行锦上添花的过程。试图通过python来完成文档从0到1的创作是不现实的。微软的office系列工具已经非常完美完善了,也发展成为一门博大精深的学问。其自身的VBA编程也无比强力,非专业人员可以考虑使用掌握。python能够完成:

•例行的但人工完成较繁琐的工作,例如自动生成报告、增加制式的表格等

•对格式进行统一

•从文档中提取表格的信息等

•抽取文档中的图表等(前面代码演示了基本思路)

 

python中处理docx的模块主要有2个:

•python-docx,处理标准docx文档

•python win32com,类似于vba的操作方法

python win32com的能力远超python-docx,但操作方法与思路类似于VBA,完全不是python的风格。本文重点介绍python-docx,它的安装很简单,如下所示。

pip install python-docx

一个Word文档,主要由下面这些内容元素构成,每个元素都有对应的方法处理:

•标题:add_heading()

•段落:add_paragraph()

•文本:add_run()

•图片:add_picture()

•表格:add_table()、add_row()、add_col()

下述代码示例了WORD的部分基本操作。

from docx import Document
from docx.shared import Inches, Pt

docxfilename = r'd:\test\auto.docx'
figname = r'd:\test\2.jpg'

document = Document()
document.add_heading('不动如山', 0)
document.add_heading('如何操作文本', level=1)
p = document.add_paragraph('测试行1\r')

p.add_run('我是粗体\r').bold = True
p.add_run('我是斜体\r').italic = True
p.add_run('我是下划线\r').underline = True
p.add_run('我的字体是24\r').font.size = Pt(24)

# 无序列表
opts = ['无序1','无序2', '无序3']
for opt in opts:
    document.add_paragraph(opt, style='List Bullet')
    
# 有序列表
opts = ['有序1','有序2', '有序3']
for opt in opts:
    document.add_paragraph(opt, style='List Number')

# 加个图
document.add_picture(str(figname), width=Inches(5))

# 生成表格,这个其实最有用处
records = (
    (1, 'DOD', '数据汇集分发'),
    (2, 'Bionic', 'Ubuntu 18.04')
)
table = document.add_table(rows=1, cols=3)
# 表头
hdr_cells = table.rows[0].cells
hdr_cells[0].text = '数量'
hdr_cells[1].text = '缩写'
hdr_cells[2].text = '含义'
# 表格数据
for tid, abbr, memo in records:
    row_cells = table.add_row().cells
    row_cells[0].text = str(tid)
    row_cells[1].text = abbr
    row_cells[2].text = memo
document.save(docxfilename)

  

  生成的DOCX文档效果如下图所示。

       用python生成WORD文档确实不是常态,这样一个文档写代码需要大量的时间,还不如直接上手WORD编辑。但使用python来解决对现有文档的一些操作却能够节省大量的时间、精力。例如,经常出现数千页的标书、著作等。由于存在多人编辑的可能性,经常一个微小更改,导致整个DOCX的版面出现混乱的现象,此时python就大有用武之地了。​​​​