栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Python

用python生成邮件正文html表格

Python 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

用python生成邮件正文html表格

一、背景

在实际工作中,有时需要写个定时脚本,每天自动发报表、监控等数据。有时需要在邮件的正文展示表格。
如果使用简单的html语法,例如代码1发邮件(代码在本文最后),则发出的表格如下图:

可以看出表格不太美观且数据杂乱。
基于此需求,开发了美化后的表格,且支持排序、合并单元格等操作。使用代码2可实现下图的表格效果

二、总体思路

相邻单元格中的值如果相同则会自动合并单元格。例如下图中的红框位置:

三、如何使用

以下是代码2中的方法,代码2见文章最后面

3.1 排序
方法:sort_data(data, sortlist)
参数【data】要排序的二维数据
参数【sortlist】排序的标准。data的第一列会按照sortlist[0]的顺序来排序,第二列按照sortlist[1]的顺序来排序。

例如 sortlist=[[‘初一’, ‘初二’], [‘语文’, ‘数学’]],那么 第一列 会按照初一、初二的顺序来排序,第二列 会按照语文、数学的顺序来排序。

3.2 数据转html表格
方法:data_to_html(data, titles, head=None, datacol=0, rowspan=False, colspan=False)
参数【data】数据二维列表
参数【titles】表头二维列表,例如[['年级', '学科']]
参数【head】表格标题,默认为None
参数【datacol】datacol=2表示从第二列开始是统计数据,统计数据不会进行合并,只有第二列之前会合并
参数【rowspan】是否进行垂直合并,默认否
参数【colspan】是否进行水平合并,默认否
3.2.1 常规表格
html1 = data_to_html(data, titles, head)
3.2.2 排序
data = sort_data(data, [sorted_grade, sorted_subject])
html2 = data_to_html(data, titles, head)
3.2.3 垂直合并表格
data = sort_data(data, [sorted_grade, sorted_subject]) #不需要排序时可以去掉这行
html3 = data_to_html(data, titles, head, 2, True, False)
3.2.4 水平合并表格
data = sort_data(data, [sorted_grade, sorted_subject]) #不需要排序时可以去掉这行
html4 = data_to_html(data, titles, head, 2, False, True)
3.2.5 垂直水平合并表格
data = sort_data(data, [sorted_grade, sorted_subject]) #不需要排序时可以去掉这行
html5 = data_to_html(data, titles, head, 2, True, True)
3.2.6 自定义宽度
data = sort_data(data, [sorted_grade, sorted_subject]) #不需要排序时可以去掉这行
html5 = data_to_html(data, titles, head, 2, True, True, [160, 120, 0, 50])
#前四列宽度依次为160 120 80 50,第五列后面的默认80,0也会转化为80
3.2.7 自定义颜色字号
data = sort_data(data, [sorted_grade, sorted_subject]) #不需要排序时可以去掉这行
html7 = data_to_html(data, titles, head, 2, True, True, [], True)
代码1
def data_to_html(data, title):
    alarm_html = ''
    for item in title:
        alarm_html += '' % item
    alarm_html += ''

    for row in data:
        alarm_html += ''
        for item in row:
            alarm_html += '' % item
        alarm_html += ""
    alarm_html += "
%s
%s
" return alarm_html if __name__ == '__main__': titles = ['表头1', '表头2', '表头3', '表头4', '表头5'] data = [ ['小学', '语文', 1, 1, 3], ['小学', '数学', 1, 5, 1], ['小学', '语文', 1, 1, 33], ['初中', '数学', 13, 1, 15], ['高中', '数学', 1, 1, 1], ['小学', '英语', 1, 8, 1], ['小学汇总', '小学汇总', 1, 1, 1], ['初中', '数学', 13, 1, 15], ['小学', '语文', 1, 1, 33], ['高中汇总', '高中汇总', 13, 1, 15] ] html1 = data_to_html(data, titles) mail_to = '123@qq.com' subject = '邮件主题' msg_txt = html1 # mail_to:邮箱 subject:主题 msg_txt:正文 send_mail(mail_to, subject, msg_txt)
代码2
def get_sort_list(l_type):
    if l_type == '年级':
        return ['小学', '初中', '高中']
    if l_type == '学科':
        return ['语文', '数学', '英语', '物理', '化学']


def sort_data(data, sortlist):
    def get_sort_num(sort_dict, item):
        for k in sort_dict:
            if k in item:
                return sort_dict[k]
        return len(sort_dict)

    for i in range(len(sortlist) - 1, -1, -1):
        sort_mode = sortlist[i]
        sort_dict = {}
        sort_len = len(sort_mode)
        for j in range(sort_len):
            sort_dict[sort_mode[j]] = j
        data = sorted(data, key=lambda x: get_sort_num(sort_dict, x[i]))
    return data


def format_data(data_c):
    data = copy.deepcopy(data_c)
    for i in range(len(data)):
        for j in range(len(data[i])):
            data[i][j] = [data[i][j], 1, 1, '', '']
    return data


def rowspan_data(data, datacol):
    datacol = min(len(data), datacol)
    last_split = [0, len(data)]  # 前一列的分片,后一列分片要在前一列分片的基础上再分
    for j in range(datacol):  # 遍历列
        next_split = [0]
        for spliti in range(len(last_split) - 1):  # 遍历分片
            item_num = {}  # 值和出现次数
            item_list = []  # 值出现顺序,去重
            for i in range(last_split[spliti], last_split[spliti + 1]):  # 遍历分片下的单元格
                item = data[i][j][0]  # 单元格的值
                if item not in item_num:
                    item_list.append(item)
                    item_num[item] = 0
                item_num[item] = item_num[item] + 1  # 统计出现次数
            item_in = set()  # 合并单元格rowspan除了第一个外都写0
            for i in range(last_split[spliti], last_split[spliti + 1]):  # 遍历分片下的单元格
                item = data[i][j][0]  # 单元格的值
                if item not in item_in:
                    data[i][j][1] = item_num[item]  # 把出现次数写进去
                    item_in.add(item)
                else:
                    data[i][j][1] = 0

            num_list = []  # 分片内值和次数
            for item in item_list:
                num_list.append(item_num[item])
            last_num = next_split[-1]
            for num in num_list:
                next_split.append(last_num + num)
                last_num = next_split[-1]
        last_split = next_split  # 生成新的分片
    return data


def colspan_data(data, datacol):
    datacol = min(len(data[0]), datacol)
    for i in range(len(data)):
        item_num = {}  # 值和出现次数
        item_list = []  # 值出现顺序,去重
        for j in range(datacol):
            item = data[i][j][0]
            if item not in item_num:
                item_list.append(item)
                item_num[item] = 0
            item_num[item] = item_num[item] + 1  # 统计出现次数
        item_in = set()  # 合并单元格rowspan除了第一个外都写0
        for j in range(datacol):
            item = data[i][j][0]  # 单元格的值
            if item not in item_in:
                data[i][j][2] = item_num[item]  # 把出现次数写进去
                item_in.add(item)
            else:
                data[i][j][2] = 0
    return data


def font_data(data, args):
    '''
    method:可根据需求对此函数进行修改
    '''
    colors = ["#00BB00", "#FF8000", "#FF0000", '#FF00FF']  # 绿、橙、红、紫
    sizes = ['2', '3', '4']
    for i in range(len(data)):
        for j in range(len(data[i])):
            data[i][j][3] = colors[i % len(colors)]
            data[i][j][4] = sizes[j % len(sizes)]
    return data


def get_sub_html(h_type, args=[]):
    colorcode = {'gray': '#ECEDF2;'}
    if h_type == 'table0':
        html = "
n" elif h_type == 'table1': html = "

n" elif h_type == 'tr0': back_color = args[0] if len(args) > 0 else '' back_color = colorcode.get(str(back_color), '') html = 'n' % ( back_color) elif h_type == 'tr1': html = 'n' elif h_type == 'th0': rowspan = args[0] if len(args) > 0 else 1 colspan = args[1] if len(args) > 1 else 1 width = args[2] if len(args) > 2 else 80 width = 80 if width == 0 else width html = '' % ( colspan, rowspan, width) elif h_type == 'th1': html = 'n' elif h_type == 'td0': rowspan = args[0] if len(args) > 0 else 1 colspan = args[1] if len(args) > 1 else 1 width = args[2] if len(args) > 2 else 80 width = 80 if width == 0 else width html = '' % ( colspan, rowspan, width) elif h_type == 'td1': html = 'n' elif h_type == 'font0': color = args[0] if len(args) > 1 else '' size = args[1] if len(args) > 1 else '' html = '' % (color, size) elif h_type == 'font1': html = 'n' else: html = '' return html def get_html_data(data, titles, head, widths=[]): html = get_sub_html('table0') if head is not None: html += get_sub_html('tr0', ['gray']) + get_sub_html('th0', [1, len(titles[0])]) + str(head) + get_sub_html('th1') + get_sub_html('tr1') for row in titles: html += get_sub_html('tr0', ['gray']) for i in range(len(row)): cell, rowspan, colspan, color, size = row[i] width = widths[i] if len(widths) > i else 80 if rowspan > 0 and colspan > 0: html += get_sub_html('th0', [rowspan, colspan, width]) + get_sub_html('font0', [color, size]) + str( cell) + get_sub_html('font1') + get_sub_html('th1') # html += get_sub_html('th0', [rowspan, colspan, width]) + str(cell) + get_sub_html('th1') html += get_sub_html('tr1') data_colors = ['gray', 'None'] color_i = 0 for row in data: if row[0][1] > 0 and row[0][2] > 0: # 换一种颜色 color_i += 1 this_color = data_colors[color_i % len(data_colors)] html += get_sub_html('tr0', [this_color]) for i in range(len(row)): cell, rowspan, colspan, color, size = row[i] width = widths[i] if len(widths) > i else 80 if rowspan > 0 and colspan > 0: html += get_sub_html('td0', [rowspan, colspan, width]) + get_sub_html('font0', [color, size]) + str( cell) + get_sub_html('font1') + get_sub_html('td1') # html += get_sub_html('td0', [rowspan, colspan, width]) + str(cell) + get_sub_html('td1') html += get_sub_html('tr1') html += get_sub_html('table1') return html def data_to_html(data, titles, head=None, datacol=0, rowspan=False, colspan=False, widths=[], font=False): ''' data:数据 type:二维数组 titles:表头 type:二维数组 如果只有一行表头,可以写成[['表头1','表头2']] head:表格标题 type:string 默认为None,没有标题。 datacol:数据起始列 type:int 数据列不会排序&合并,例如datacol=3,则除了前三列往后都是数据,合并时也不会进行合并 rowspan:是否垂直合并 value:True or False 合并前请先排序,调用sort_data方法即可 colspan:是否水平合并 value:True or False widths:每列宽度 type:一维数组 数组的每个值分别代表了每一列的宽度,默认80,写0也是80 font:是否需要自定义字号颜色 value:True or False 为True时表示,需要根据需求改变字号和颜色,需要修改font_data方法 ''' titles = format_data(titles) data = format_data(data) if rowspan == True and datacol > 0: # 垂直合并 titles = rowspan_data(titles, len(titles[0])) data = rowspan_data(data, datacol) if colspan == True and datacol > 0: # 水平合并 titles = colspan_data(titles, len(titles[0])) data = colspan_data(data, datacol) if font == True: data = font_data(data, []) html = get_html_data(data, titles, head, widths) return html def get_example_data(): head = '表格标题' titles = [['大表头1', '大表头1', '大表头2', '大表头3', '大表头3'], ['小表头1', '小表头2', '小表头3', '小表头2', '小表头5']] data = [ ['小学', '语文', 1, 1, 3], ['小学', '数学', 1, 5, 1], ['小学', '语文', 1, 1, 33], ['初中', '数学', 13, 1, 15], ['高中', '数学', 1, 1, 1], ['小学', '英语', 1, 8, 1], ['小学汇总', '小学汇总', 1, 1, 1], ['初中', '数学', 13, 1, 15], ['小学', '语文', 1, 1, 33], ['高中汇总', '高中汇总', 13, 1, 15] ] return head, titles, data def run_example(): # 排序用的年级学科列表 sorted_grade = get_sort_list('年级') sorted_subject = get_sort_list('学科') # 常规表格 head, titles, data = get_example_data() html1 = data_to_html(data, titles, head) # 排序 # 先用第一列按年级排序,再用第二列按学科排序,不需要排序的列可以补空数组[],前面的列排序优先级高 head, titles, data = get_example_data() data = sort_data(data, [sorted_grade, sorted_subject]) html2 = data_to_html(data, titles, head) # 垂直合并表格 head, titles, data = get_example_data() data = sort_data(data, [sorted_grade, sorted_subject]) html3 = data_to_html(data, titles, head, 2, True, False) # 水平合并表格 head, titles, data = get_example_data() data = sort_data(data, [sorted_grade, sorted_subject]) html4 = data_to_html(data, titles, head, 2, False, True) # 垂直水平合并表格 head, titles, data = get_example_data() data = sort_data(data, [sorted_grade, sorted_subject]) html5 = data_to_html(data, titles, head, 2, True, True) # 垂直水平合并表格并自定义宽度 head, titles, data = get_example_data() data = sort_data(data, [sorted_grade, sorted_subject]) html6 = data_to_html(data, titles, head, 2, True, True, [160, 120, 0, 50]) # 自定义颜色字号 head, titles, data = get_example_data() data = sort_data(data, [sorted_grade, sorted_subject]) html7 = data_to_html(data, titles, head, 2, True, True, [], True) # 各种功能都用上试试 head, titles, data = get_example_data() data = sort_data(data, [sorted_grade, sorted_subject]) html8 = data_to_html(data, titles, head, 2, True, True, [160, 120, 0, 50, 200], True) mail_to = '123@qq.com' subject = '邮件主题' msg_txt = html1 + html2 + html3 + html4 + html5 + html6 + html7 + html8 send_mail(mail_to, subject, msg_txt) if __name__ == '__main__': run_example()
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/349732.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号