python-docx常用方法总结

由于最近有任务需要自动生成word报告,因此学习了一些-docx的使用方法,在此总结 。
目前网上相关的资料不算太多,且大多数都很简单 。有一些稍微复杂的需求往往找不到答案,很多想要的方法这个库似乎并没有直接提供 。在git上看,这个包最新的一次更新是2021年 。希望有大神能接过这个接力棒,继续维护更新 。
一、基础内容 1、对象
整个操作过程实际就是围绕着对象进行“增删改查” 。因此,首先需要创建一个文档对象
# pip install python-docxfrom docx import Documentdocument = Document()
上述操作会创建一个新的空白文档,如果我们想打开已有的模板文档,只需指定其路径即可
document = Document('配置/基础模板.docx')
当所有的操作完成后我们需要保存文档
document.save(os.path.join(os.getcwd(), 'xx报告.docx'))
2、插入标题
from docx.enum.text import WD_PARAGRAPH_ALIGNMENT# 添加一个二级标题head = document.add_heading(level=2)# 标题居中head.alignment = WD_PARAGRAPH_ALIGNMENT.CENTER# 标题的内容run = head.add_run('绿水青山就是金山银山')# 字体run.font.name = 'Times New Roman'
3、插入一个段落
from docx.shared import Pt# 先获得段落对象p = document.add_paragraph()# 首行缩进20磅p.paragraph_format.first_line_indent = Pt(20)# 设置段落格式fmt = p.paragraph_format# 设置行间距fmt.line_spacing = 1.5# 一个段落可以有多个run对象,主要考虑同一段落的文字可能有多种样式run = p.add_run('段落内容1')
这个run对象,一开始我也没太理解 。已经添加了一个段落对象,直接填充段落内容不就行了嘛 。段落对象下面再添加一个run对象是什么意思?原来这个run对象就是一段文本整体,这样你可以对这个整体进行统一样式设置 。没有run对象的话,你就只能对段落对象进行统一设置,那就无法实现下面的效果
对一个run对象设置字体、颜色、大小等方法如下
from docx.shared import RGBColor# 设置字体run.font.name = 'Times New Roman'# 字体大小run.font.size = Pt(20)# 字体颜色run.font.color.rgb = RGBColor(255, 0, 0)# 加粗run.font.bold = True# 斜体run.font.italic = True
我们一般习惯使用“小四”、“五号”来表示字体大小,但在程序里只支持传入磅值,下面是字号和磅值的对应关系 。
字号和磅值对应关系
字号
磅值
字号
磅值
八号
小三
15
七号
5.5
三号
16
小六
6.5
小二
18
六号
7.5
二号
22
小五
小一
24
五号
10.5
一号
26
小四
12
小初
【python-docx常用方法总结】36
四号
14
初号
42
4、插入一个表格
添加表格一般有两种情况 。第一种是创建表格时就明确行和列的数量,然后循环往里添加内容
arr = np.array([['A', '001'], ['B', '002'], ['C', '003']])# 如果要加表头,rows=4,表格预定义样式详见官网table = document.add_table(rows=3, cols=2, style='Colorful List')# 添加内容for i, row in enumerate(table.rows):for j, cell in enumerate(row.cells):# 获取单元格中的段落对象paragraph = cell.paragraphs[0]# 和上面一样,这里的run可以设置一些属性run = paragraph.add_run(str(arr[i, j]))
第二种情况是,提前并不确定表格的行列,需要根据数据情况临时添加 。则可以先创建一个1*1的表格,然后向右增加列以及向下增加行
from docx.shared import Inches# 自动行高,无须指定table.add_row()# 列宽需要指定,1英寸table.add_column(width=Inches(1))
从上述代码可以看到,一个表格(table)对象由多个行(row)对象组成,一个行(row)对象又由多个单元格(cell)对象组成 。单元格对象包含段落对象,有了段落对象我们就可以添加文字并设置样式 。
5、插入图片
# 指定图片文件目录,指定插入后图片所占尺寸(会根据原始尺寸和指定尺寸自动缩放)document.add_picture('xx.png', width=Pt(500), height=Pt(400))
6、插入页眉
from docx.shared import Cmsection = document.sections[0]header = section.headerparagraph = header.paragraphs[0]# 也可以直接插入文字run = paragraph.add_run()# 这里是插入logo图片run.add_picture("logo.png", height=Cm(0.91))
二、常见问题 1、如何指定中文字体
前面我们指定的字体是新罗马体,没什么问题 。但如果我们直接将其改为'宋体'或'Sim Sun',都不会生效 。这是因为宋体是非西文字体,默认是西文字体,因此不识别 。需要如下操作
from docx.oxml.ns import qnrun.font.name = '宋体'# 设置东亚字体run._element.rPr.rFonts.set(qn('w:eastAsia'), '宋体')
2、如何自定义样式
一份文档中,标题、正文、表格内容样式基本是统一的 。因此,可以预先自定义一些样式,并命名 。后续即可直接通过名称应用这些样式,而不用每次都去定义 。有点像格式刷的效果 。
from docx.enum.style import WD_STYLE_TYPEstyle = document.styles.add_style('my_style', WD_STYLE_TYPE.CHARACTER)style.font.color.rgb = RGBColor(255, 0, 0)style.font.name = '黑体'style._element.rPr.rFonts.set(qn('w:eastAsia'), '黑体')style.font.size = Pt(20)style.font.bold = Truerun1 = p.add_run('社会主义核心价值观是社会主义核心价值体系的内核')run2 = p.add_run('比心')# 将自定义的样式应用在run2上run2.style = 'my_style'run3 = p.add_run('体现社会主义核心价值体系的根本性质和基本特征')
3、如何替换模板文档中文字
如果我们想基于一个模板文档进行二次编辑,可以在模板文档中设置一些占位 。通过替换占位达到编辑的目的 。如果是替换表格内容,可遍历单元格cell,通过对cell.text重新赋值即可 。
for p in document.paragraphs:if p.text == '占位1':# 清除原有内容;也可以直接令p.text = '新的内容'p._element.clear()run = p.add_run('新的内容')run.font.size = Pt(18)
使用模板文档时有一个巨坑,新建的空白文档是支持预定义的样式的,而模板文件不一定 。比如你在创建表格时指定style=' List',实际并不一定会生效 。具体原因目前还没搞清楚 。具体模板文件有哪些预定义的样式,可以通过下述方法获知 。
for style in document.styles:print(style.name)
预定义的样式可查看官网,下面是部分截图
4、如何合并多个文档
new_doc = Document() # 以此类推,将多个文档(doc2,doc3)的内容添加进去for elem in document1.element.body:new_doc.element.body.append(elem)
但这种方法有一个缺点,无法复制图片 。下面提供一种不使用-docx但有效的方法 。
from win32com.client import Dispatchcwd = os.getcwd()word = Dispatch('Word.Application')doc_files = word.Documents.Add()# 插入文档doc_files.Application.Selection.Range.InsertFile(os.path.join(cwd, 'tmp1.docx'))doc_files.Application.Selection.Range.InsertFile(os.path.join(cwd, 'tmp2.docx'))doc_files.SaveAs(os.path.join(cwd, '合并.docx'))# 一定要关闭word.Quit()