最近在工作中一直接触到统计月报这块的文档,之前一直是把结果打印在Jupyter lab上,然后通过复制粘贴的方式放入Word文档里,但是最近统计月报的数量越来越多,作者连复制粘贴也懒得想做了 ,遂学习了python-docx的使用,将所有结果直接写入word,最后写了这个文章,希望也能帮助到大家解放自己的双手~
完整Github码源地址,有帮助到大家的话欢迎点一下星星:Python-docx_Sample
环境 | 信息 |
---|---|
系统 | WIN10 |
软件 | Jupyter Lab 2.2.6 |
语言 | Python 3.8.5 |
python-docx | 0.8.10 |
完整Github码源 | Python-docx_Sample |
为什么要单独把库的安装单独列一块,因为作者一开始没注意名称,直接pip install docx,结果发现根本没法使用,最后查了半天才发现作者像个智障一样 下了一个“同名”的库,原来这个库写作python-docx
,用作docx
。
什么叫写作和用作,请大家分别看安装语句和引用语句就能理解了。
安装语句
pip install python-docx
引用语句
from docx import Document
在作者这里,其实十分不推荐大家直接用python-docx直接生成新的Word文档,因为这样不仅会增加开发的难度(例如:页眉页脚、创建样式、创建样式和创建样式),如果文档需要修改,代码的修改会更加困难!因此作者推荐的方式是,先手动制作一份Word模板,再使用python-docx通过修改内容的方式去编写Word文档。
作者设置页眉页脚的方法是在模板里就提前设置好,原因很简单,就像普通编辑word文档一样,在使用 python-docx 修改和插入段落、图片和表格的时候是不会影响页眉页脚的。
from docx import Document,shared
import random #这里只是为生成一些数据用,使用时记得去掉哦
由于 python-docx 返回的的表格是一个特殊的 table 格式,所以读取和写入都需要一定的步骤才能完成 (和pandas比起来真是差远了) 。因此作者特地配备了一个自己写的_docx类来辅助表格的读写(包括一个pandas数据的转换功能),在这里也开放给大家供大家方便使用,使用的时候可以根据需要对 table_writer 模块进行调整。
class _docx:
def table_reader(table):
table_list = []
for i, row in enumerate(table.rows): # 读每行
row_content = []
for cell in row.cells: # 读一行中的所有单元格
c = cell.text
if '\n' in c: c=c.replace('\n','') # 删除换行符
row_content.append(c)
table_list.append(row_content)
return table_list
def table_filler(table,table_list):
for i, row in enumerate(table.rows): # 读每行
if i==0: continue # 跳过首行
for j,cell in enumerate(row.cells): # 读一行中的所有单元格
par = cell.paragraphs[0]
par.text = str(table_list[i][j]) # 写入内容
par.style.name = '表内容' # 添加样式
def table_transfer(pd_df):
array = np.array(pd_df.reset_index())
array_list = array.tolist()
return array_list
def table_writer(table,pd_df):
table_data = _docx.table_transfer(pd_df)
table_list = _docx.table_reader(table)
table_list[1:] = table_data
_docx.table_filler(table,table_list)
filename = 'Sample_Template.docx'
document = Document(filename)
在配置内容的时候往往需要对比,因此打印段落号和内容能很好的协助读写内容。
此外,document.paragraphs
无法读取到图片和表格,如果需要查看图片和表格,可以使用 document.tables) 和
document.inline_shapes`。
for i,parag in enumerate(document.paragraphs):
print('段落{}'.format(i),parag.text)
table = document.tables[0]
table_list = _docx.table_reader(table)
table_list
查询了模板里的样式后,在添加段落、表格、图片的时候就可以通过给.style.name
赋值直接使用已有的样式,十分方便实用!
查询方式:
for s in document.styles:
print(s.type,s.name)
i = 8 # 总标题行
document.paragraphs[i].text,i = '程序员种菜指南',i+1 # 写入内容,i=i+1
i += 1 # 再加一行到标题一行
document.paragraphs[i].text,i = '一、程序员为什么种菜',i+1 # 写入内容,i=i+1
document.paragraphs[i].text,i = '1.1、种菜的好处',i+1 # 写入内容,i=i+1
content = '种菜可以吃。'
document.paragraphs[i].text,i = content,i+1 # 写入内容,i=i+1
document.paragraphs[i].text,i = '1.2、程序员种菜的好处',i+1 # 写入内容,i=i+1
content = '程序员可以批量种菜。'
document.paragraphs[i].text,i = content,i+1 # 写入内容,i=i+1
document.paragraphs[i].text,i = '二、种菜流程',i+1 # 写入内容,i=i+1
document.paragraphs[i].text,i = '2.1、种菜流程图',i+1 # 写入内容,i=i+1
content = '程序员种菜主要流程是播种、施肥、浇水和收割。'
document.paragraphs[i].text,i = content,i+1 # 写入内容,i=i+1
picture = '程序员种菜指南.png'
document.paragraphs[i].add_run().add_picture(picture,height=shared.Cm(6),width=shared.Cm(10)) # 在段落内插入图片
i += 1
document.paragraphs[i].text,i = '2.2、种菜成果表',i+1 # 写入内容,i=i+1
for row in range(1,len(table_list)):
for col in range(1,len(table_list[row])):
table_list[row][col] = random.randint(0,10) # 程序员'收集'并填写结果
_docx.table_filler(table,table_list) # 将结果写入表格
document.save('Sample_Result.docx')
重要的话要说三次!只要把模板Word文档的页眉、页脚、样式设置好,必要的时候可以多设置几个样式。那么剩下的只需要在读取之后往对应的段落或者表格塞东西就好了,真的很方便哦!!