写在前面
01. 创作背景
本人在自动化部门使用 python 实现自动化,在空闲时间整理如下常用的 python 调用 word 来实现自动化的办公,也希望笔者的疑惑能得到大家的回答,当然随着不断学习,笔者也会不断更新,希望大家多多支持。
02. 使用软件以及版本号
笔者使用的是 PyCharm ,其版本号如下
PyCharm 2022.1 (Community Edition) Build #PC-221.5080.212, built on April 12, 2022 Runtime version: 11.0.14.1+1-b2043.25 amd64 VM: OpenJDK 64-Bit Server VM by JetBrains s.r.o. Windows 10 10.0 GC: G1 Young Generation, G1 Old Generation Memory: 2048M Cores: 8 Non-Bundled Plugins: com.intellij.zh (221.262) |
使用 Python 实现自动化 word
01. python-docx 库的安装:
pip install python-docx
使用方法:
from docx import Document
import docx
02. 新建docx文档 / 打开文档:
document = Document()
# document = docx.Document()
# 传入 xxx.docx 就会打开对应文件夹, 不传参数就会新建 docx
又或者查找某个路径下的文档,这里以查找当前文件夹下的docx为例
"""
Path.cwd():当前文件夹路径
"""
from pathlib import Path
from docx import Document
# 遍历当前工作目录下的文件并以doc返回第一个找到的docx文件
for file_path in Path.cwd().iterdir():
if file_path.is_file() and str(file_path).endswith(".docx"):
doc = Document(doc_path)
break
以上方法可以打开当前目录下的字典序最小的 docx 文件 (把 break 去掉可以遍历所有 docx)
03. 在文档末尾添加段落(并设置样式)
from docx import Document
doc = Document()
doc.add_paragraph("请输入文本", style=doc.styles["Normal"])
doc.save("test.docx")
如上代码在运行时会创建新docx并在docx文段末添加对应文本并设置其格式为 正文,如果不知道,内置的格式可以使用以下方法查看
from docx import Document
doc = Document("test.docx")
for style in doc.styles:
print(style.name)
04. 在文档中添加新的样式格式
样式格式的设置,相当于设置了一个字体的模板,对于经常使用的格式来说会比较方便
如果docx没有内置您需要的文字格式,那么有一种最简单的方法就是外部设置一个模板(一个集合了您需要所有格式的docx,这样可以使用导入的方法白嫖内置格式)。当然,也可以折磨自己,学习如何在 python 中设置自己的 styple ,但是在设置的时候记得看看 docx 中有没有使用过相同的类型名字,不然...可能会把内置的格式给覆盖了...
如下代码为例,设置了自己的正文格式与标题格式,以及常用的图片解释的文字格式。
from docx import Document
doc = Document("test.docx")
"格式创建"
"标题_1"
heding_1_style = doc.styles.add_style('My_Normal', 1)
heding_1_style.font.bold = True
heding_1_style.font.size = Pt(12)
heding_1_style.font.name = 'Arial'
# heding_1_style.font.color.rgb = RGBColor(0, 0, 0)
heding_1_style.paragraph_format.alignment = WD_PARAGRAPH_ALIGNMENT.LEFT
"标题_2"
heding_2_style = doc.styles.add_style('My_Heading 2', 1)
heding_2_style.font.bold = False
heding_2_style.font.size = Pt(15)
heding_2_style.font.name = 'Calibri Light'
# heding_2_style.font.color.rgb = RGBColor(0, 0, 0)
heding_2_style.paragraph_format.alignment = WD_PARAGRAPH_ALIGNMENT.LEFT
"题注"
caption_style = doc.styles.add_style('My_caption', 1)
caption_style.font.bold = False
caption_style.font.size = Pt(10)
caption_style.font.name = 'Calibri Light'
caption_style.font.color.rgb = RGBColor(0, 0, 0)
caption_style.paragraph_format.alignment = WD_PARAGRAPH_ALIGNMENT.CENTER
从上到下分别设置了字体加粗、字体大小,字体格式,字体颜色,字体位置(靠左 or 居中),听说能设置以下功能,但还未测试
名称(name) | 指定你要创建的样式的名称 |
段落样式(paragraph) | 定义段落的格式,如对齐方式、缩进、行距等 |
字符样式(character) | 定义文本的格式,如字体、字号、颜色等 |
编号样式(numbering) | 定义段落的编号格式,如项目符号、编号等 |
表格样式(table) | 定义表格的格式,包括表格边框、对齐方式等 |
链接样式(link) | 定义超链接的格式,如颜色、下划线等 |
样式类型(type) | 指定样式的类型,如段落样式、字符样式等 |
05. 在文档末尾添加表格(并设置格式)
1. 表格的插入
from docx import Document
from docx.enum.text import WD_PARAGRAPH_ALIGNMENT
from docx.oxml import parse_xml
from docx.oxml.ns import nsdecls
doc = Document("test.docx")
table = doc.add_table(rows=2, cols=4, style='Table Grid')
# 内容
text = [
["No.", "no", "Department", "department"],
["Location,", "department", "Equipment number", "eq_num"]
]
for row in range(2):
for col in range(4):
table.cell(row, col).text = text[row][col]
table.cell(row, col).paragraphs[0].alignment = WD_PARAGRAPH_ALIGNMENT.CENTER # 水平居中
if not col & 1:
# 设置单元格颜色, 这里为浅灰色
shading_elm = parse_xml(r'<w:shd {} w:fill="D8D8D8"/>'.format(nsdecls('w')))
table.cell(row, col)._tc.get_or_add_tcPr().append(shading_elm)
doc.save("test.docx")
在更好格式代码中,这里应该添加 Row 和 Column 来记录行列数,并将其包装在函数中,方便调用。
如果在文档格式中不需要单独修改某个单元格的颜色,则建议以迭代器的方式遍历表格会更好。
# 建立表格并填入text对应位置的信息(下标从 0 开始)
def build_table(Row, Column, text):
table = doc.add_table(rows=Row, cols=Column, style='Table Grid')
for row in range(Row):
for col in range(Column):
table.cell(row, col).text = text[row][col]
table.cell(row, col).paragraphs[0].alignment = WD_PARAGRAPH_ALIGNMENT.CENTER # 水平居中
if not col & 1:
shading_elm = parse_xml(r'<w:shd {} w:fill="D8D8D8"/>'.format(nsdecls('w')))
table.cell(row, col)._tc.get_or_add_tcPr().append(shading_elm)
2. 设置行高和列宽
默认是每个单元格的大小是一样的
# 调整表格中每一行的高度
for row in table.rows:
row.height = 1.0 # 设置行高为1.0英寸
# 调整表格中每一列的宽度
for col in table.columns:
col.width = 1.5 # 设置列宽为1.5英寸
如果是不统一修改,可以提前定义 width 和 height 方便后续更改
table = doc.add_table(Row, Column)
width = []
height = []
table.autofit = False
for row in range(Row):
for column in range(Column):
table.cell(row, column).width = width[column]
table.cell(row, column).height = height[row]
3. 一些笔者未解决的小问题:
1. 在以上代码中只能做表格的水平居中对齐,没有垂直居中对齐,找了很久都找不到(笔者真的很需要这个...)
2. 上述代码中修改单元格颜色使用了类内的东西,破坏了类的完整性,有没有别的方法修改单元格颜色呢
06. 在文档末尾添加图片
from docx import Document
from docx.shared import Inches
# 创建一个新的文档
doc = Document()
k = 0.64 # 设置图片的比例系数
# 添加段落并设置\t来调整图片位置
paragraph = doc.add_paragraph("\t\t")
# 将绝对路径下的图片添加到段落中
pic_name = "图片绝对路径/相对路径"
paragraph.add_run().add_picture(pic_name, width=Inches(14 * k), height=Inches(8 * k))
# 题注
doc.add_paragraph('题注', style=doc.styles["题注格式"])
插入时候的 \t 插入是用来调整图片位置的,当然用空格也可以,笔者认为这样调整比较灵活(纯个人想法)。而在图片导入时,笔者认为固定图片的大小比例会比较好,所以,仅仅调节图片的横纵放缩比k,可以保证图片不会因为多次变换而变形。
当然,也有通过插入一个表格,在表格里面放置图片的方法来对齐图片。
# 添加一个表格,1行1列
table = doc.add_table(rows=1, cols=1)
# 获取第一个单元格
cell = table.cell(0, 0)
# 设置单元格的水平和垂直居中对齐
cell.vertical_alignment = WD_ALIGN_VERTICAL.CENTER
cell.paragraphs[0].alignment = WD_ALIGN_HORIZONTAL.CENTER
# 在单元格中插入图片并设置大小
run = cell.paragraphs[0].add_run()
picture = run.add_picture('图片.jpg', width=Inches(2), height=Inches(2))
而对于导入图片的函数可以调节以下参数:旋转角度、图片的宽高、透明度等。
07. 在文档末尾添加分页
doc.add_section(WD_SECTION_START.NEW_PAGE)
08. 格式总览
Understanding Styles — python-docx 1.1.0 documentation |
以上网站包含了常用的格式,方便查看,当然也可以用代码调用的方式查看
09. 调整段落间距以及行距倍数
from docx import Document
from docx.shared import Pt
doc = Document('test.docx')
# 遍历文档中的段落并调整段间距和行间距
for paragraph in doc.paragraphs:
# 调整段间距
paragraph.paragraph_format.space_after = Pt(12) # 设置段后间距为12磅
paragraph.paragraph_format.space_before = Pt(6) # 设置段前间距为6磅
# 调整行间距
paragraph.paragraph_format.line_spacing = 1.5 # 设置行间距为1.5倍
这种方法好像可以调整段落的间距的比例系数,好像不是默认值也可以(狂喜)
10. 段落文字的颜色修改
1. 字体颜色修改
p = doc.add_paragraph("红色字的文本")
p.runs[0].font.color.rgb = RGBColor(255, 0, 0) # 红色
注意这里不能用类似 p.style.font.color.rgb 的方式修改,不然就会把该 styple 的所有格式的文字颜色都修改了
2. 字体背景颜色的修改
from docx.oxml import OxmlElement
from docx.oxml.ns import qn
shade_obj = OxmlElement('w:shd')
shade_obj.set(qn('w:fill'), 'FFFF00')
r = document.add_paragraph().add_run('黄色背景')
rpr_obj = OxmlElement('w:rPr')
rpr_obj.append(shade_obj)
r._element.append(rpr_obj)
这里的代码是借鉴 http://t.csdnimg.cn/ehqsP 中的思路
11. python 对 word 段落的操作
1. 对段落的遍历
# 遍历文档中的段落并输出内容和格式
for paragraph in doc.paragraphs:
print(paragraph.text, paragraph.style.name)
2. 对段落的关键字提取
至此,可以使用 python 在段落中做检索,以搜索包含关键字的所有段落
# 搜索目标文段
target_text = '目标文段'
found_paragraphs = []
for paragraph in doc.paragraphs:
if target_text in paragraph.text:
found_paragraphs.append(paragraph)
3. 替换 word 中原段落内容信息
# 由于是替换, 必须是打开原有文件
doc = Document("test.docx")
# 这里仅做样例, 实际可以通过关键字检索出要替换的段落后再替换
paragraph = doc.paragraphs[1]
# 替换段落中的文字 (此方法默认格式为正文)
new_text = "替换后的文字"
paragraph.text = new_text
doc.save("test.docx")
4. 删除 word 中的指定段落
# 这里仅做样例, 实际可以通过关键字检索出要替换的段落后再删除
paragraph = doc.paragraphs[1]
# 删除段落
def delete_paragraph(_paragraph):
# _element属性是表示段落在Word文档中对应XML元素的属性
p = _paragraph._element
p.getparent().remove(p)
_paragraph._p = _paragraph._element = None
return p
delete_paragraph(paragraph)
12. 修改 word 纸张大小以及方向
1. word 纸张大小
section = doc.sections[0]
# 标准 A4
section.page_width = Cm(21)
section.page_height = Cm(29.7)
print(section.page_width.cm)
print(section.page_height.cm)
2. 纸张方向
section.page_width, section.page_height = section.page_height, section.page_width
13. 页边距和装订线
# 上下左右页边距 单位cm
section.top_margin = Cm(2)
section.bottom_margin = Cm(2)
section.left_margin = Cm(3)
section.right_margin = Cm(3)
# 装订线(左)
section.gutter = Cm(1)
14. 页眉和页脚
header.paragraphs[0].add_run("页眉")
footer.paragraphs[0].add_run("页脚")
15. 以上头文件
from pathlib import Path
from docx import Document
from docx.enum.text import WD_PARAGRAPH_ALIGNMENT
from docx.oxml import OxmlElement
from docx.oxml import parse_xml
from docx.oxml.ns import nsdecls
from docx.oxml.ns import qn
from docx.shared import Inches
from docx.shared import Pt
结束语:
本来是想把 excel 也写了,但是发现太长了,先写到这里,(也方便查看,主要是因为懒)。希望大家如果发现有 bug 也可以提出一下,笔者有补充的也会及时更新的...
如果有什么因为引用连接忘记放的地方也希望提出一下,就这样吧 doge