人力資源部每個月發工資條,以前靠人工手動一條一條的復制,200多號員工,差不多需要耗費一天時間。
用python寫個腳本,分分鍾的事情就可以全部發送完。
我這邊工資表如下圖
姓名在C列,郵箱在B列。
發送完,這樣顯示
收到的郵件是這樣
還有這樣
# !/usr/bin/env python # -*- coding:utf-8 -*- # Author:Hiuhung Wan from openpyxl import load_workbook from email.mime.text import MIMEText # 郵件正文 from email.header import Header # 郵件頭 import smtplib, time # 登錄 def login(smtp_server, ssl_port, sender, passwd): smtp_obj = smtplib.SMTP_SSL(smtp_server, ssl_port) smtp_obj.login(sender, passwd) return smtp_obj # 發郵件 def send_email(smtp_obj, sender, rec_list, msg): smtp_obj.sendmail(sender, rec_list, msg) def op_excel(smtp_obj, filename:str): # 加載excel文件 data_only=True,自動計算公式 wb = load_workbook(filename, data_only=True) # 使用xlsx文件,不要使用xls sheet = wb.active # 先取列名 table_col_name = [] for row in sheet.rows: for cell in row: # print(cell.value) table_col_name.append(cell.value) break # 循環excel for row in sheet.iter_rows(min_row=2): table_col_html = '<thead>' # 表頭 row_text = '<tr>' # 開始一行 list_del = [] # 准備減掉的字段 list_finally = table_col_name[:] # 最終的字段 for cell in row: # print(cell.value, type(cell.value)) # None <class 'NoneType'> 0 <class 'int'> if cell.value == None or cell.value == 0: # 數據為零或空 # print(cell.col_idx) # 列數,從1開始數 list_del.append(table_col_name[cell.col_idx - 1]) else: row_text += f'<td>{cell.value}</td>' row_text += '</tr>' # 結束一行 # 去掉值為零或空的字段 for i in list_del: list_finally.remove(i) # 重寫首行 for i in list_finally: table_col_html += f'<th>{i}</th>' table_col_html += '</thead>' # 員工姓名 name = row[2].value # 從0開始數,第2列 staff_email = row[1].value # 員工郵箱地址 從0開始數,第1列 mail_body_context = f'''<h3>{name}:你好!</h3> <p>請查收你2020年5月的工資條。</p> <table border="1px solid black"> {table_col_html} {row_text} </table> ''' msg = MIMEText(mail_body_context, 'html', 'utf-8') msg['From'] = Header('HHHH人力資源部', 'utf-8') # 發送者 msg['To'] = Header('HHHH員工', 'utf-8') # 接收者 msg['Subject'] = Header('HHHH 2020年5月工資條', 'utf-8') # 主題 # 發郵件 try: send_email(smtp_obj, sender, [staff_email], msg.as_string()) print(f'成功發送工資條到{staff_email}--{name}...') except smtplib.SMTPException as e: print('Error:無法發送郵件.Case:%s' % e) if __name__ == '__main__': time_start = time.time() smtp_server = 'smtp.qq.com' # SMTP服務器 ssl_port = 465 # SMTP端口 sender = '123456789@qq.com' # 發件人郵箱 passwd = '**********' # 發件人密碼 filename = "2020年5月員工工資表.xlsx" smtp_obj = login(smtp_server, ssl_port, sender, passwd) op_excel(smtp_obj, filename) time_end = time.time() print('腳本執行完畢,耗時%.3f秒。' % (time_end - time_start))
支持自動去掉值為空或為零的列。如獎金、請假等。
當然,也可以豎向排列工資條。
需要修改一下op_excel方法
def op_excel(smtp_obj, filename: str): # 操作表格 # 加載excel文件 data_only=True,自動計算公式 wb = load_workbook(filename, data_only=True) # 使用xlsx文件,不要使用xls sheet = wb.active # 先取列名 table_col_name = [] for row in sheet.rows: for cell in row: # print(cell.value) table_col_name.append(cell.value) break # 循環excel for row in sheet.iter_rows(min_row=2): # table_col_html = '<thead>' # 表頭 row_text = '' list_del = [] # 准備減掉的字段 list_finally = table_col_name[:] # 最終的字段 list_money = [] # 金額 for cell in row: # print(cell.value, type(cell.value)) # None <class 'NoneType'> # 0 <class 'int'> if cell.value is None or cell.value == 0: # 數據為零或空 # print(cell.col_idx) # 列數,從1開始數 list_del.append(table_col_name[cell.col_idx - 1]) else: list_money.append(cell.value) # 去掉值為零或空的字段 for i in list_del: list_finally.remove(i) # 員工姓名 name = row[1].value # 從0開始數,第2列 staff_email = row[2].value # 員工郵箱地址 從0開始數,第1列 # <tr>添充 for index in range(len(list_finally)): # print(list_finally[index],list_money[index]) row_text += '<tr>' # 開始一行 row_text += f'<td>{list_finally[index]}</td>' row_text += f'<td>{list_money[index]}</td>' row_text += '</tr>' # 結束一行 mail_body_context = f'''<h3>{name}:你好!</h3> <p>請查收你2020年5月的工資條。</p> <table border="1px solid black"> <thead> <th>項目</th> <th>值</th> </thead> {row_text} </table> ''' msg = MIMEText(mail_body_context, 'html', 'utf-8') msg['From'] = Header('HHHH人力資源部', 'utf-8') # 發送者 msg['To'] = Header('HHHH員工', 'utf-8') # 接收者 msg['Subject'] = Header('HHHH 2020年5月工資條', 'utf-8') # 主題 # 發郵件 try: send_email(smtp_obj, sender, [staff_email], msg.as_string()) print(f'成功發送工資條到{staff_email}--{name}...') except smtplib.SMTPException as e: print('Error:無法發送郵件.Case:%s' % e)
效果如下
源碼參考了alex在B站的分享。
https://www.bilibili.com/video/BV1UK4y1t7Ui?t=1395