分享

实例5:用Python批量生成word版邀请函

 Four兄 2019-08-23

每到年终时,公司都要举办年会,总结当年的得失。还有就是组织个晚会,表演些节目,抽奖......当然,还有,赏大餐一顿。人事部的妹子这时就发愁了,忙碌地进行各种准备不说,还要给供应商,政府部门发邀请函。这个邀请函其实除了受邀者的名字不同外,其它信息完全一样,纯粹的体力活。这种脏累活儿,就交给Python来干吧。


首先,我们需要将所有受邀者的公司名和代表姓名填入一个Excel表格。然后做好邀请函的模板,在需要填字的地方打上小星星“****”,然后就让Python来玩填字游戏啦。话不多说,直入主题,代码走一波......

#1.从Excel文件获取受邀人单位和名字
from openpyxl import load_workbook
wb=load_workbook('data/name_list.xlsx')
ws=wb['name']
names=[]
for row in range(2,ws.max_row+1):
company=ws['A'+str(row)].value
name=ws['B'+str(row)].value
names.append(' {} {} '.format(company,name))
names
>>[' 供应商1 王波 ',
' 供应商2 刘海洋 ',
' 供应商3 少和光 ',
' 供应商4 真凡巧 ',
' 供应商5 鲁鸿运 ',
' 政府1 乐清霁 ',
' 政府2 郎绮琴 ',
' 政府3 贝芳懿 ',
' 政府4 哈彦君 ']

我们首先导入openpyxl模块中的load_workbook模块。openpyxl是一个可读取Excel的第三方库。load_workbook()可打开一个现有的Excel文件(或叫工作簿)。我们使用load_workbook(path)读取文件,并存在变量wb里面。我们可以想象变量就是容器,用来储存各种数据,这里的wb就是这个容器的名字。wb存储的是整个工作簿的内容,我们知道一个Excel有几个工作表“Sheet”,接下来我们需要选取我们所需要的“Sheet”,也就是名字叫'name'的那张表。当然你可以给这个工作表起自己喜欢的名字,在写代码的时候把wb['name']中的'name'字样替换成你的个性化名字即可。


然后定义一个空列表names来存储受邀人单位和名字信息。随后我们遍历工作表,将所有信息提取出来存入列表names。因为工作表第一行是标题,所以我们从第2行开始,最大一行+1结束range(2,ws.max_row+1)。之所以要加1,是因为range(1,5)只能取到“1,2,3,4”四个值,5是取不到的。ws.max_row指工作表的总行数。然后我们开始提取公司名称,company=ws['A'+str(row)].value,当row取2时,就相当于将工作表中A2(即A列2行单元格的值)单元格的值传给了company变量。获取姓名也是类似的操作方式。


然后将公司名称和姓名排一下版,再加入names列表。' {} {} '.format(company,name)这个格式化字符串函数就完成了这个操作。我们在公司名和姓名之间及前后都加入了一个空格,这样在最终的邀请函上看起来就是这样的:“尊敬的 供应商1 王波 先生/女士:”。不留空格的话,就变成这样了:“尊敬的供应商1王波先生/女士:”,似乎有点不和谐。格式化字符串可以理解为,将format(company,name)括号中的值依次填入前面的{}。

# 2.批量填字,存为不同的word文件
import docx #导入处理word的库,无耻地直接使用别人造好的轮子
doc=docx.Document('data/邀请函.docx')
for name in names:
doc.paragraphs[1].runs[2].text=name
doc.save('data/邀请函_{}.docx'.format(name))

受邀人信息获取完成后,我们就可以开始批量生成邀请函了。首先导入处理word的库,无耻地直接使用别人造好的轮子。建立一个容器doc,来盛装打开的邀请函,docx.Document('data/邀请函.docx')为固定写法,括号内填写邀请函模板的路径及文件名。doc可理解为就是这个名为“邀请函”word文件。然后遍历names列表,将里面的信息逐个写入word文件的第二段的第三个run,即doc.paragraphs[1].runs[2].text=name,相当于直接用name的值“ 供应商1 王波 ”替换掉****。其中的run指的是每一段中的不同的格式,比如一段中有常规的,有加粗的,有斜体的,有不同颜色的字,那么就有好几个run。

那我们怎么知道****是第二段第三个run呢?通过我们制作的“邀请函”模板,我们知道****位于第二段(即doc.paragraphs[1],因为是从0开始计数,所以0表示第一段,1就表示第二段)。请注意word中若有空行,也算一段,比如模板中的'ABC有限公司'开头的那一段已经算是第四段了。我么将第二段的所有run打印出来,就可以找到****所在的run了。

doc=docx.Document('data/邀请函.docx')
for run in doc.paragraphs[1].runs:
print(run.text)

>>尊敬

****
先生
/
女士

我们可以看到其中有7个runs,虽然“尊敬的”三个字格式是一样的,但是还是被识别为两个单独的run了,可能这个库主要用来处理英文文档,拿来搞中文有些水土不服。不管它了,让它乱识别吧。通过以上的run打印,我们简单粗暴地数下去,可以知道****在第三个run,即run[2]
然后逐个保存为单个的文件,并在给新的word文件命名时加上受邀人的信息doc.save('data/邀请函_{}.docx'.format(name))。得到的结果如下: 

了方便打印,可以使用word自带的合并功能将所有邀请函合并为一个word文件。打开第一个邀请函word文档,然后单击【插入】选项卡下的【对象】菜单中的【文件中的文字】选项,选择剩余的所有邀请函word文件,点插入,搞定!

所有源代码和说明都在Jupyter notebook上完成,所用到的Excel 资料已上传GitHub, 欢迎Fork或下载到本地随意玩。。。转载请注明出处,谢谢。

GitHub链接:

https://github.com/weidylan/Office_Automation_by_Using_Python

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多