提示:没学过python,只是日常工作中总是需要用到邮件合并,想偷懒。所以复制了一些代码并根据自己需要进行了更改
关键字:Python 邮件合并 pandas mailmerge
例如:已知你负责给几个优秀学生填写《年度优秀学生审批表》
现有一份班级花名册给你,你要从花名册里查找学生姓名、年龄、地址、父母工作单位诸如此类。
以往的做法是筛选出来,用excel 和word 邮件合并,但是每次邮件合并都需要重新设置,
《年度优秀学生审批表》几乎每年不变,所以偷懒用Python一键生成。
提示:以下是本篇文章正文内容,下面案例可供参考
搜了一下,很多例子是通过导入xlrd库和mailmerge,xlrd库需要生成一个单独的excel表,就是把这10个优秀学生单独摘出来,重新做一个xlsx,作为引用的数据源。
用pandas,直接读取班级总花名册即可,通过姓名筛选出这10个优秀学生,不需要额外生成xlsx。
也许xlrd也可以,但是我不会,也没看到类似文章。
怎么设置word模板,插入域这个很多教程。这里不重复了。
导入库如下(示例):
from mailmerge import MailMerge ##pip install docx-mailmerge
import pandas as pd
# 不需要导入xlrd 和 OS
花名册 =pd.read_excel(r'F:\\pythontest\\花名册6月4日数据.xls')
筛查条件 = ['张三', '李四','王二']
list1 = []
for i in 筛查条件:
筛选结果 = 花名册[花名册['姓名'].str.contains(i)]
list1.append(筛选结果)
优等生花名册 = pd.concat(list1)
列名 = 优等生花名册.columns.to_list()
docx模板= r'F:/Pythontest/测试模板.docx'
nrow = 优等生花名册.shape[0]
list_temp = []
for key in range(0, nrow):
dict_temp = {}
dict_temp['姓名'] = str(优等生花名册.iloc[key, 列名.index('姓名')])
dict_temp['年龄'] = str(优等生花名册.iloc[key, 列名.index('年龄')])
list_temp.append(dict_temp)
with MailMerge(docx模板) as doc:
doc.merge_templates(list_temp, separator='page_break')
output = r'E:\测试\证明文件3.docx'
doc.write(output)
print('邮件合并成功')
# 写给小白,也是写给自己,弄明白每步代码是怎么来的,代表什么意思
花名册 =pd.read_excel(r'F:\\pythontest\\huamingce\\花名册6月4日数据.xls') # 以只读的方式打开原始花名册数据
筛查条件 = ['张三', '李四','王二'] # 输入姓名的方式设置。筛查条件 = input('请输入筛选字段,请使用空格作为分隔符:').split(' ')
list1 = []
for i in 筛查条件:
筛选结果 = 花名册[花名册['姓名'].str.contains(i)] #.str.contains(i) 判断i里的数据在 哪一列。本例是通过罪名列筛选
list1.append(筛选结果)
优等生花名册 = pd.concat(list1)
# 优等生花名册.to_excel('顽固犯花名册.xls')
列名 = 优等生花名册.columns.to_list() # 将列名转为为list列表 to_list ,优等生花名册.columns是把首行提取出来,等下查找用,它的格式是method, to_list()函数是将 优等生花名册.columns 转换为list
docx模板= r'F:/Pythontest/教育改造/一键填表/测试模板.docx'
nrow = 优等生花名册.shape[0] #判断花名册有几行,等下循环要用
list_temp = [] # 空列表 循环用
for key in range(0, nrow): #for key in range(1,ws.nrows):#从索引1,第2行开始遍历到最后1行
dict_temp = {} # 空字典 循环用
dict_temp['姓名'] = str(优等生花名册.iloc[key, 列名.index('姓名')]) # cell_value(行数,列数):获取单元格的值;
dict_temp['年龄'] = str(优等生花名册.iloc[key, 列名.index('年龄')]) #
list_temp.append(dict_temp) #list1.append(dic)#把每次遍历行列得到的字典加入列表
with MailMerge(docx模板) as doc: # with 是python打开文件并自动关闭的方式。?抄来的,不理解没关系,能用就行。
doc.merge_templates(list_temp, separator='page_break')##separator=separator 'page_break'是换页符,'textWrapping_break'是换行符。'column_break', 'textWrapping_break', 'continuous_section',分节符'evenPage_section', 'nextColumn_section', 'nextPage_section', 'oddPage_section'
output = r'E:\测试\证明文件3.docx'
doc.write(output)
print('邮件合并成功')
代码如下(示例):
from mailmerge import MailMerge ##pip install docx-mailmerge
import pandas as pd
import os.path # 读取文件路径用
花名册 =pd.read_excel(r'F:\\pythontest\\huamingce\\花名册6月4日数据.xls')
筛查条件 = ['张三', '李四','王二']
list1 = []
for i in 筛查条件:
筛选结果 = 花名册[花名册['姓名'].str.contains(i)]
list1.append(筛选结果)
优等生花名册 = pd.concat(list1)
列名 = 优等生花名册.columns.to_list()
docx模板= r'F:/Pythontest/教育改造/一键填表/测试模板.docx'
filepath = os.path.dirname(docx模板)
nrow = 优等生花名册.shape[0]
list_temp = []
for key in range(0, nrow): #for key in range(1,ws.nrows):
with MailMerge(docx模板) as doc:
doc.merge(姓名 = str(优等生花名册.iloc[key, 列名.index('姓名')]),
年龄 = str(优等生花名册.iloc[key, 列名.index('年龄')])
)
output = filepath + r'\证明-{}.docx'.format(str(优等生犯花名册.iloc[key, 列名.index('姓名')])) # 以证明-姓名的方式生成每个文件
doc.write(output)
print('邮件合并成功')
# 写给小白,也是写给自己,弄明白每步代码是怎么来的,代表什么意思
花名册 =pd.read_excel(r'F:\\pythontest\\huamingce\\花名册6月4日数据.xls')
筛查条件 = ['张三', '李四','王二']
list1 = []
for i in 筛查条件:
筛选结果 = 花名册[花名册['姓名'].str.contains(i)] #.str.contains(i) 判断i里的数据在 哪一列。本例是通过 姓名 列筛选
list1.append(筛选结果)
优等生花名册 = pd.concat(list1)
列名 = 优等生花名册.columns.to_list() # 将列名转为为list列表 to_list ,优等生犯花名册.columns是把首行提取出来,等下查找用,它的格式是method, to_list()函数是将 顽固犯花名册.columns 转换为list
docx模板= r'F:/Pythontest/教育改造/一键填表/测试模板.docx' # 花名册 =pd.read_excel(r'F:\\pythontest\\huamingce\\花名册6月4日数据.xls') 也可以直接读取xlsx
filepath = os.path.dirname(docx模板) # 保存到docx 模板所在目录
nrow = 优等生花名册.shape[0] #判断花名册有几行,等下循环要用
list_temp = [] # 空列表 循环用
for key in range(0, nrow): #for key in range(1,ws.nrows):#从索引1,第2行开始遍历到最后1行
with MailMerge(docx模板) as doc:
doc.merge(姓名 = str(优等生花名册.iloc[key, 列名.index('姓名')]), # 这里和合并一个文件有区别,用的是doc.merge ,合并一个文件用的是 doc.merge_templates
年龄 = str(优等生花名册.iloc[key, 列名.index('年龄')])
)
output = filepath + r'\证明-{}.docx'.format(str(优等生花名册.iloc[key, 列名.index('姓名')])) # 以证明-姓名的方式生成每个文件
doc.write(output)
print('邮件合并成功')
搜了一下,很多例子是通过导入xlrd库和mailmerge,pandas 是基于NumPy 的一种工具,该工具是为了解决数据分析任务而创建的。
1、导入mailmerge错误
代码如下(示例):
ImportError: cannot import name 'MailMerge' from 'mailmerge'
之前默认安装了很多库,其中一个mailmerge库和我们用的docx-mailmerge 重名了
pip uninstall mailmerge #卸载自动装的mailmerge包
pip install docx-mailmerge # 重新安装docx-mailmerge包
然后退出编辑器,重新打开就可以了
2、合并一个文件和以各自名字新建文件的代码区别
合并为一个文件的方法是 doc.merge_templates
doc.merge_templates(list_temp, separator='page_break')
output = r'E:\测试\证明文件3.docx'
doc.write(output)
合并为多个文件的方法是doc.merge
doc.merge(姓名 = str(优等生花名册.iloc[key, 列名.index('姓名')]),
年龄 = str(优等生花名册.iloc[key, 列名.index('年龄')])
)
output = filepath + r'\证明-{}.docx'.format(str(优等生犯花名册.iloc[key, 列名.index('姓名')])) # 以证明-姓名的方式生成每个文件
3、存在BUG
查找3个同学,张三、李四、王二。如果有两个张三,或办理有人叫王二、又有人叫王二小。生成的优等生花名册就会有两个张三,有一个王二、一个王二小。
精准匹配的话用下面代码
筛查条件 = ['张三', '李四','王二']
优等生花名册 = 花名册[花名册['姓名'].isin(筛查条件])]
每年评审工作一键生成了