人力資源部每個月發工資條,以前靠人工手動一條一條的復制,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
