吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 4817|回复: 11
收起左侧

[Python 转载] python使用tkinter&pandas&smtplib读取Excel并发送邮件

  [复制链接]
liangyun 发表于 2019-5-16 17:36
本帖最后由 liangyun 于 2019-5-16 17:42 编辑

效果图:
for52.png


1. 功能介绍:

当然是因为15号发工资啦,每次都是等呀等呀等呀等呀,最后终于等到一张来自Excel的工资条截图

于是我就希望能够学以致用试试,但是写好了又不敢给领导看~哈哈哈,发给大家批评批评

首先,需要一个Excel咯,这里我用的office2019,如果是旧版本的文件就看第60行注释

软件功能就是,可以读取一个Excel文件并将每一条信息发送到相应的邮箱中

要发送的信息很方便改动

2. python代码:

这里将html代码和python分开放了,显得没那么臃肿,使用的时候将24行字符串填进去即可

import _thread
import smtplib
import webbrowser
from email.header import Header
from email.mime.text import MIMEText
from tkinter import *
from tkinter import filedialog, messagebox

import pandas as pd

class App:
    # 全部
    all_info: int = 0
    # 发送失败
    err_info: int = 0
    # 发送成功
    suc_info: int = 0
    # 当前数据
    t: pd.DataFrame = None
    # 表示正在执行的邮件发送线程的数量
    counter: int = 0
    # html模板,为了防止打包打不进去,干脆写进来了
    html: str = """"""

    def __init__(self, _root):
        self.root = _root
        self.center_window()
        # 布局
        # line_0
        self.path = StringVar()
        # self.path.set("请将路径复制到此框或通过右边按钮选择路径")
        self.path.set("C:/Users/xy/Desktop/工资.xlsx")
        self.path_e = Entry(self.root, textvariable=self.path, width=72)
        self.path_e.grid(row=0, column=0, columnspan=3, padx=5, pady=5)
        self.path_button = Button(self.root, text='选择路径', command=self.select_path)
        self.path_button.grid(row=0, column=3, padx=5, pady=5)

        # line_1
        self.info = Listbox(self.root, width=82)
        self.info.grid(row=1, column=0, padx=5, pady=5, columnspan=4)

        # line_2
        self.show_table_b = Button(self.root, text='预览文件', command=self.show_table)
        self.show_table_b.grid(row=2, column=1, padx=5, pady=5)
        self.send_email_b = Button(self.root, text='发送邮件', command=self.send)
        self.send_email_b.grid(row=2, column=2, padx=5, pady=5, sticky='w')

        # line_3
        self.msg = StringVar()
        self.msg.set('邮件发送状态')
        self.msb_l = Label(self.root, textvariable=self.msg)
        self.msb_l.grid(row=3, column=0, columnspan=3, padx=5, pady=5, sticky='w')
        # # 获取html模板
        # with open('a.html', 'r') as f:
        #     self.html = f.read()

    def select_path(self):
        path_ = filedialog.askopenfilename(title='打开工资表', filetypes=[('Excel', '*.xlsx')])
        # 如果要打开旧版本Excel文件,可以将下面这一行取消注释。顺便将上面一行注释掉。也可以自己写完整的文件后缀。
        # path_ = filedialog.askopenfilename(title='打开工资表')
        if path_ != "":
            self.path.set(path_)

    # 窗口居中,有bug,在电脑设置了“‘缩放与布局-->更改文本、应用等项目的大小’”不为100%时会有偏差。跟分辨率和像素有关,无心解决
    def center_window(self, w=600, h=280):
        ws = self.root.winfo_screenwidth()
        hs = self.root.winfo_screenheight()
        x = (ws // 2) - (w // 2)
        y = (hs // 2) - (h // 2)
        self.root.geometry(f'{w}x{h}+{x}+{y}')

    # 就是通过浏览器读取一下Excel信息,应用空间很小,估计只有在电脑上没有安装Excel才能用到吧~
    def show_table(self):
        # 读Excel
        if self.get_data():
            return
        self.all_info = self.t.index.size
        self.t.to_html('a.html')
        webbrowser.open('a.html')

    # 读取并发送。
    def send(self):
        # 读Excel
        if self.get_data():
            return
        self.all_info = self.t.index.size
        # 防止按钮被点坏了
        self.send_email_b['state'] = 'disable'
        for index, row in self.t.iterrows():
            # 多线程防止界面假死
            _thread.start_new_thread(self.send_email, (row.values,))

    # 发送邮件并更新状态
    def send_email(self, data: list):
        self.counter += 1
        # 替换模板内容
        html = self.html
        for index, item in enumerate(data):
            html = html.replace('{' + str(index) + '}', str(item))
        receiver = data[-1]
        # 发送邮箱的用户名和授权码(不是登录邮箱的密码)
        username = 'tianxiezijideyouxiangzhanghao@qq.com'
        password = 'haiyouzijidemima'

        # 邮件主题
        mail_title = '工资发放情况'

        # 邮件内容, 格式, 编码
        message = MIMEText(html, 'html', 'utf-8')
        message['From'] = u'小言<' + username + '>'
        message['To'] = receiver
        message['Subject'] = Header(mail_title, 'utf-8')

        try:
            smtp = smtplib.SMTP()
            smtp.connect('smtp.qq.com')
            smtp.login(username, password)
            smtp.sendmail(username, receiver, message.as_string())
            smtp.quit()
            state = '成功'
            self.suc_info += 1
        except smtplib.SMTPException as e:
            state = str(e)
            self.err_info += 1
        # 添加状态
        self.info.insert('end', data[0].ljust(10, '-') + receiver.ljust(25, '-') + state)
        self.counter -= 1
        if self.counter == 0:
            self.send_email_b['state'] = 'normal'
        # 更新信息
        self.msg.set(
            f'邮件发送状态:共计 {self.all_info} 条信息,'
            f'已发送{self.suc_info + self.err_info}条,'
            f'剩余{self.all_info - self.suc_info - self.err_info}条,'
            f'其中成功发送{self.suc_info}条,'
            f'失败{self.err_info}条')

    def get_data(self):
        try:
            self.t = pd.read_excel(self.path.get())
            self.t.fillna('', inplace=True)
            return False
        except Exception as e:
            messagebox.showerror('出现异常', str(e))
            return True

if __name__ == '__main__':
    # 写的不规范,但是无奈不知道规范的怎么写~
    root = Tk()
    # 设置全局字体,在四处寻求无果后于百度知道找到了一位大佬在2011年写出的答案
    root.option_add('*Font', 'Fira 10')
    root.title('通过邮件发放工资表')
    root.resizable(0, 0)
    App(root)
    root.mainloop()
3. html代码

<!-- Row Highlight Javascript -->
<script>
    window.onload = function () {
        var tfrow = document.getElementById('tfhover').rows.length;
        var tbRow = [];
        for (var i = 1; i < tfrow; i++) {
            tbRow[i] = document.getElementById('tfhover').rows[i];
            tbRow[i].onmouseover = function () {
                this.style.backgroundColor = '#ffffff';
            };
            tbRow[i].onmouseout = function () {
                this.style.backgroundColor = '#f0c169';
            };
        }
    };
</script>
<style type="text/css">
    table.tftable {
        font-size: 12px;
        color: #333333;
        width: 100%;
        border-width: 1px;
        border-color: #ebab3a;
        border-collapse: collapse;
    }

    table.tftable th {
        font-size: 12px;
        background-color: #e6983b;
        border-width: 1px;
        padding: 8px;
        border-style: solid;
        border-color: #ebab3a;
        text-align: left;
    }

    table.tftable tr {
        background-color: #f0c169;
    }

    table.tftable td {
        font-size: 12px;
        border-width: 1px;
        padding: 8px;
        border-style: solid;
        border-color: #ebab3a;
    }
</style>

<table id="tfhover" class="tftable" border="1">
    <tr>
        <th>姓名</th>
        <th>岗级</th>
        <th>考勤小计</th>
        <th>岗位工资,绩效奖金</th>
        <th>餐补</th>
        <th>出差补助</th>
        <th>司龄</th>
        <th>学历</th>
        <th>证书</th>
        <th>话补</th>
        <th>地区补贴</th>
        <th>C奖金</th>
        <th>B奖金</th>
        <th>A奖金</th>
        <th>D奖金</th>
        <th>E奖金</th>
        <th>F奖金</th>
        <th>工资扣款</th>
        <th>应发工资</th>
        <th>社保</th>
        <th>公积金</th>
        <th>个税</th>
        <th>实发工资</th>
        <th>邮箱</th>
    </tr>
    <tr>
        <td>{0}</td>
        <td>{1}</td>
        <td>{2}</td>
        <td>{3}</td>
        <td>{4}</td>
        <td>{5}</td>
        <td>{6}</td>
        <td>{7}</td>
        <td>{8}</td>
        <td>{9}</td>
        <td>{10}</td>
        <td>{11}</td>
        <td>{12}</td>
        <td>{13}</td>
        <td>{14}</td>
        <td>{15}</td>
        <td>{16}</td>
        <td>{17}</td>
        <td>{18}</td>
        <td>{19}</td>
        <td>{20}</td>
        <td>{21}</td>
        <td>{22}</td>
        <td>{23}</td>
    </tr>
</table>
最后是Excel表格的样式,我就不上传文件了,反正没有具体的特殊要求

姓名 岗级 考勤小计 岗位工资,绩效奖金 餐补 出差补助 司龄 学历 **证书 话补 地区补贴 A奖 B奖 C奖 D奖 E奖 F奖 工资扣款 应发工资 社保 公积金 个税 实发工资 邮箱
小言 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 youxiang@qq.com
凉云 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 youxiang@qq.com

免费评分

参与人数 7吾爱币 +9 热心值 +6 收起 理由
djqiuzhe + 1 + 1 我很赞同!
qingmei + 1 + 1 用心讨论,共获提升!
天空宫阙 + 1 谢谢@Thanks!
zzzain46 + 3 + 1 用心讨论,共获提升!
niebaohua + 1 + 1 热心回复!
为海尔而战 + 1 + 1 支持原创!
slofLeo + 1 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

 楼主| liangyun 发表于 2019-12-2 17:35
tonrry 发表于 2019-11-30 12:10
能做个发短信的不?

短信一般走短信平台, 费用也比我们普通的手机卡消费低, 这种平台他们自己会提供接口供你使用,例如阿里云https://www.aliyun.com/product/sms这种,不过它的起步价太低了, 没有体验包,https://cloud.baidu.com/product/sms.html百度的可能对于试用来说成本更低一些,我只看了这两家,你可以多看看,文档写的也非常详细
 楼主| liangyun 发表于 2019-6-12 14:33
念天悠 发表于 2019-6-10 19:32
你好,python可以读取某一个excel里面的参数然后把它填入另一个有特定格式的excel表里面吗

可以的,但是需要xlrd和xlwt,你可以百度了解一下,单纯填写难度并不大
ee789852 发表于 2019-5-16 17:51
潇未然 发表于 2019-5-16 17:58
刚好有其他表格需要发。可以套用。感谢~
slofLeo 发表于 2019-5-17 01:03
很不错啊
 楼主| liangyun 发表于 2019-5-17 08:30
潇未然 发表于 2019-5-16 17:58
刚好有其他表格需要发。可以套用。感谢~

终于能写出来有用的程序了,好开心

点评

厉害哦,有第一步就有第二步~工作越来越方便~  详情 回复 发表于 2019-5-17 09:20
潇未然 发表于 2019-5-17 09:20
liangyun 发表于 2019-5-17 08:30
终于能写出来有用的程序了,好开心

厉害哦,有第一步就有第二步~工作越来越方便~
念天悠 发表于 2019-6-10 19:32
你好,python可以读取某一个excel里面的参数然后把它填入另一个有特定格式的excel表里面吗
hbkx 发表于 2019-6-13 09:11
谢谢分享,学习了
787821 发表于 2019-7-2 21:54
念天悠 发表于 2019-6-10 19:32
你好,python可以读取某一个excel里面的参数然后把它填入另一个有特定格式的excel表里面吗

可以的啊,可以参考pandas和xlwings~!
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-11-16 17:54

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表