赞
踩
由于最近有任务需要自动生成word报告,因此学习了一些python-docx的使用方法,在此总结。
目前网上相关的资料不算太多,且大多数都很简单。有一些稍微复杂的需求往往找不到答案,很多想要的方法这个库似乎并没有直接提供。在git上看,这个包最新的一次更新是2021年。希望有大神能接过这个接力棒,继续维护更新。
整个操作过程实际就是围绕着document对象进行“增删改查”。因此,首先需要创建一个文档对象
- # pip install python-docx
- from docx import Document
- document = Document()
上述操作会创建一个新的空白文档,如果我们想打开已有的模板文档,只需指定其路径即可
document = Document('配置/基础模板.docx')
当所有的操作完成后我们需要保存文档
document.save(os.path.join(os.getcwd(), 'xx报告.docx'))
- 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'
- 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
-
我们一般习惯使用“小四”、“五号”来表示字体大小,但在程序里只支持传入磅值,下面是字号和磅值的对应关系。
字号 | 磅值 | 字号 | 磅值 |
八号 | 5 | 小三 | 15 |
七号 | 5.5 | 三号 | 16 |
小六 | 6.5 | 小二 | 18 |
六号 | 7.5 | 二号 | 22 |
小五 | 9 | 小一 | 24 |
五号 | 10.5 | 一号 | 26 |
小四 | 12 | 小初 | 36 |
四号 | 14 | 初号 | 42 |
添加表格一般有两种情况。第一种是创建表格时就明确行和列的数量,然后循环往里添加内容
- 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):
- # 获取单元格中的段落对象 cell.add_paragraph()将新增一个段落对象,体现出来的效果就是换行
- 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)对象组成。单元格对象包含段落对象,有了段落对象我们就可以添加文字并设置样式。
- # 指定图片文件目录,指定插入后图片所占尺寸(会根据原始尺寸和指定尺寸自动缩放)
- document.add_picture('xx.png', width=Pt(500), height=Pt(400))
- from docx.shared import Cm
- section = document.sections[0]
- header = section.header
- paragraph = header.paragraphs[0]
- # 也可以直接插入文字
- run = paragraph.add_run()
- # 这里是插入logo图片
- run.add_picture("logo.png", height=Cm(0.91))
前面我们指定的字体是新罗马体,没什么问题。但如果我们直接将其改为'宋体'或'Sim Sun',都不会生效。这是因为宋体是非西文字体,默认是西文字体,因此不识别。需要如下操作
- from docx.oxml.ns import qn
- run.font.name = '宋体'
- # 设置东亚字体
- run._element.rPr.rFonts.set(qn('w:eastAsia'), '宋体')
一份文档中,标题、正文、表格内容样式基本是统一的。因此,可以预先自定义一些样式,并命名。后续即可直接通过名称应用这些样式,而不用每次都去定义。有点像格式刷的效果。
- from docx.enum.style import WD_STYLE_TYPE
-
- style = 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 = True
-
- run1 = p.add_run('社会主义核心价值观是社会主义核心价值体系的内核')
- run2 = p.add_run('比心')
- # 将自定义的样式应用在run2上
- run2.style = 'my_style'
- run3 = p.add_run('体现社会主义核心价值体系的根本性质和基本特征')
如果我们想基于一个模板文档进行二次编辑,可以在模板文档中设置一些占位。通过替换占位达到编辑的目的。如果是替换表格内容,可遍历单元格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='Colorful List',实际并不一定会生效。具体原因目前还没搞清楚。具体模板文件有哪些预定义的样式,可以通过下述方法获知。
- for style in document.styles:
- print(style.name)
预定义的样式可查看官网,下面是部分截图
- new_doc = Document()
-
- # 以此类推,将多个文档(doc2,doc3)的内容添加进去
- for elem in document1.element.body:
- new_doc.element.body.append(elem)
但这种方法有一个缺点,无法复制图片。下面提供一种不使用python-docx但有效的方法。
- from win32com.client import Dispatch
-
- cwd = 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()
- from docx import Document
- from docx.shared import Cm
-
- doc = Document()
-
- rows = 3
- cols = 4
- table = doc.add_table(rows, cols, style='Colorful List')
- # 设置每列的宽度,这里实际是一个比例,根据总宽度14.6计算每个单元格宽度
- col_widths = (1, 1, 1, 3)
- for idx, width in enumerate(col_widths):
- table.cell(0, idx).width = Cm(14.6 * col_widths[idx] / sum(col_widths))
- # 填充内容
- for i in range(rows):
- for j in range(cols):
- table.cell(i, j).text = f'Cell {i + 1},{j + 1}'
-
- doc.save('table_with_col_width.docx')
![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。