------------------------------------
该需求有两个表格,第一个表格是计算薪资的,第二个表格是员工信息,包括姓名和邮箱
这里只要把薪资表按照每个人截图放到一个文件夹中,从信息表取姓名和截图名字做对应,然后发送邮件
1、工资表样式,名字必须和员工信息表一致
2、员工信息表样式注意列,我没有做行列自定义选择的功能,现在是写死的,当然也可以加个变量自定义
软件样式:
本程序是根据员工信息表的基础,来判定是否成功发送邮件,如果工资表没有这个人,那么也没有这个人的截图,那这个人就未发送。
授权码就是qq邮箱的 第三方授权
--------------------------------------------------
用到的包pillow 、xlwings、email、tkinter(界面UI)
-----------------------------------
这里不多废话,直接贴代码
1 from PIL import ImageGrab 2 import xlwings as xw 3 import smtplib 4 from email.mime.multipart import MIMEMultipart 5 from email.mime.text import MIMEText 6 from email.mime.image import MIMEImage 7 import tkinter as tk # 使用Tkinter前需要先导入 8 from tkinter import filedialog 9 import os 10 import time 11 12 class Monitor(): 13 def __init__(self): 14 #错误信息 15 self.error = [] 16 self.nosend = [] 17 self.dictname =[] 18 19 #判断文件夹是否已经创建 20 def is_exists(self,dir): 21 if not os.path.exists(dir): 22 os.makedirs(dir) 23 24 # 截图函数 25 def excel_catch_screen(self,wbs,save_floder,shot_sheetname): 26 sheet = wbs.sheets(shot_sheetname) # 选定sheet 27 all = sheet.used_range # 获取有内容的range 28 all.api.CopyPicture() # 复制图片区域 29 sheet.api.Paste() # 粘贴 30 pic = sheet.pictures[0] # 当前图片 31 pic.api.Copy() # 复制图片 32 img = ImageGrab.grabclipboard() # 获取剪贴板的图片数据 33 self.is_exists(save_floder) # 判断文件夹 34 try: 35 img.save(save_floder+'/'+shot_sheetname + ".png") # 保存图片 36 pic.delete() # 删除sheet上的图片 37 except: 38 print('%s 截图失败!'%shot_sheetname) 39 40 41 # 邮件函数 42 # 1、查看邮件excel中的所有对应值 (name,email) 43 def get_info(self,dicts,info): 44 app = xw.App(visible=False, add_book=False) 45 wb = app.books.open(info) 46 sheet = wb.sheets[0] 47 maxrow = sheet.used_range.last_cell.row # 最大行 48 for row in range(2,maxrow+1): 49 name = sheet.range('B' + str(row)).value 50 email = str(sheet.range('J' + str(row)).value).replace('@qq.com','') 51 dicts[name] = email.replace('.0','')+'@qq.com' 52 wb.close() 53 app.quit() 54 #2、发送邮件 55 def send_png(self,subject,sender,name,receivers,password,png): 56 message = MIMEMultipart('related') 57 message['Subject'] = subject 58 message['From'] = sender 59 message['To'] = receivers 60 content = MIMEText('<html><body><img src="cid:imageid" alt="imageid"></body></html>','html','utf-8') 61 message.attach(content) 62 file=open(png, "rb") 63 img_data = file.read() 64 file.close() 65 img = MIMEImage(img_data) 66 img.add_header('Content-ID', 'imageid') 67 message.attach(img) 68 try: 69 server=smtplib.SMTP_SSL("smtp.qq.com",465) 70 server.login(sender,password) #"填写qq邮箱的授权码" 71 server.sendmail(sender,receivers,message.as_string()) 72 server.quit() 73 print ("邮件发送成功") 74 except smtplib.SMTPException as e: 75 self.error.append(name) 76 pass 77 78 def work(self,subject,sender,password,excel_name,info_name): 79 sheetname=[] 80 app = xw.App(visible=False, add_book=False) 81 wb = app.books.open(excel_name) 82 num = len(wb.sheets) 83 #用sheetname 接受所有员工的sheet名 84 for i in range(1,num): 85 sheet = wb.sheets[i] 86 sheetname.append(sheet.name) 87 #循环截屏并保存到自定义文件夹下 88 save_floder = './'+subject 89 for name in sheetname: 90 self.excel_catch_screen(wb,save_floder,name) 91 time.sleep(5) 92 #存储员工信息表 93 dicts = {} 94 self.get_info(dicts,info_name) 95 96 wb.close() # 不保存,直接关闭 97 app.quit() 98 #循环发送邮件 #发送邮件 根据excel中的邮件人姓名和地址进行匹配已保存的png图片,顺序发送 99 # 遍历字典,在文件夹中找对应图片 100 for name, receivers in dicts.items(): 101 self.dictname.append(name) 102 for file in os.listdir(save_floder): 103 self.nosend.append(file.replace('.png','')) 104 for name, receivers in dicts.items(): 105 if name in self.nosend: 106 self.send_png(subject,sender,name,receivers,password,save_floder+'/'+name+'.png') 107 print(sender,receivers,name,save_floder+'/'+name+'.png') 108 else: 109 self.error.append(name) 110 111 def main(self): 112 # password = 'zbtwghtciidmbaii' 113 # 界面化处理 114 window = tk.Tk() 115 window.title('邮件群发V1.0') 116 # 第3步,设定窗口的大小(长 * 宽) 117 window.geometry('400x400') # 这里的乘是小x 118 119 def selectPath(): 120 entry_excel_name = filedialog.askopenfilename(title='选择工资计算表', 121 initialdir='/', filetypes=[('.xlsx','*.xlsx'),('全部文件','*.*')]) 122 return entry_excel_name 123 def selectPath1(): 124 entry_info_name = filedialog.askopenfilename(title='选择员工信息表', 125 initialdir='/', filetypes=[('.xlsx','*.xlsx'),('全部文件','*.*')]) 126 return entry_info_name 127 128 def exec(entry_excel_name,entry_info_name): 129 try: 130 subject = entry_title.get() 131 sender = entry_usr_name.get() 132 password = entry_usr_pwd.get() 133 excel_name = entry_excel_name 134 info_name = entry_info_name 135 136 self.work(subject,sender,password,excel_name,info_name) 137 if len(self.error) == 0: 138 text.insert('insert','所有邮件发送成功') 139 else: 140 text.insert('insert','%s 邮件发送失败' % self.error) 141 142 except Exception as e: 143 if e == 'No such file: ': 144 text.insert('insert','没有选择文件') 145 else: 146 text.insert('insert',e) 147 148 149 # 用户信息 150 tk.Label(window, text='邮件标题:', font=('Arial', 10)).place(x=10, y=5) 151 tk.Label(window, text='Q Q 号:', font=('Arial', 10)).place(x=10, y=35) 152 tk.Label(window, text='授权码:', font=('Arial', 10)).place(x=10, y=65) 153 154 subject = tk.StringVar() 155 subject.set('XX年XX月薪资') 156 entry_title = tk.Entry(window, textvariable=subject, font=('Arial', 10)) 157 entry_title.place(x=120, y=5) 158 159 var_usr_name = tk.StringVar() 160 var_usr_name.set('[email protected]') 161 entry_usr_name = tk.Entry(window, textvariable=var_usr_name, font=('Arial', 10)) 162 entry_usr_name.place(x=120, y=35) 163 164 var_usr_pwd = tk.StringVar() 165 entry_usr_pwd = tk.Entry(window, textvariable=var_usr_pwd, font=('Arial', 10), show='*') 166 entry_usr_pwd.place(x=120, y=65) 167 168 #程序运行框 169 text = tk.Text(window, show=None) 170 text.place(relx=0.01,rely=0.3,relwidth=0.98,relheight=0.7) 171 172 # 执行按钮 173 btn_login = tk.Button(window, text='立即执行',height = 4, width = 15 ,command= lambda : exec(selectPath(),selectPath1())) 174 btn_login.place(x=275, y=6) 175 176 # 主窗口循环显示 177 window.mainloop() 178 179 if __name__ == '__main__': 180 app = Monitor() 181 app.main()