------------------------------------
該需求有兩個表格,第一個表格是計算薪資的,第二個表格是員工信息,包括姓名和郵箱
這裏只要把薪資表按照每個人截圖放到一個文件夾中,從信息表取姓名和截圖名字做對應,然後發送郵件
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()