当前位置: 首页 > 工具软件 > Mail2Bug > 使用案例 >

【Python 邮件合并 pandas mailmerge】

锺离锦
2023-12-01

提示:没学过python,只是日常工作中总是需要用到邮件合并,想偷懒。所以复制了一些代码并根据自己需要进行了更改

关键字:Python 邮件合并 pandas mailmerge


前言

例如:已知你负责给几个优秀学生填写《年度优秀学生审批表》

现有一份班级花名册给你,你要从花名册里查找学生姓名、年龄、地址、父母工作单位诸如此类。

思考

以往的做法是筛选出来,用excel 和word 邮件合并,但是每次邮件合并都需要重新设置,

《年度优秀学生审批表》几乎每年不变,所以偷懒用Python一键生成。

提示:以下是本篇文章正文内容,下面案例可供参考

一、为什么要用pandas?

搜了一下,很多例子是通过导入xlrd库和mailmerge,xlrd库需要生成一个单独的excel表,就是把这10个优秀学生单独摘出来,重新做一个xlsx,作为引用的数据源。

用pandas,直接读取班级总花名册即可,通过姓名筛选出这10个优秀学生,不需要额外生成xlsx。

也许xlrd也可以,但是我不会,也没看到类似文章。

怎么设置word模板,插入域这个很多教程。这里不重复了。

二、使用步骤

1.邮件合并为一个word文档,引入库

导入库如下(示例):

from mailmerge import MailMerge ##pip install docx-mailmerge
import pandas as pd
# 不需要导入xlrd 和 OS

2.代码区(所有变量我都用中文标示)


​花名册 =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('邮件合并成功')

 2.邮件合并为多个word文档,并以学生名字命名

代码如下(示例):

from mailmerge import MailMerge ##pip install docx-mailmerge
import pandas as pd
import os.path # 读取文件路径用

2.代码区

花名册 =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(筛查条件])]

总结

每年评审工作一键生成了

 类似资料: