在实际工作中,有时需要写个定时脚本,每天自动发报表、监控等数据。有时需要在邮件的正文展示表格。
如果使用简单的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也会转化为803.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 = '| %s | ' % item alarm_html += '
| %s | ' % item alarm_html += "
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 == 'tr0': back_color = args[0] if len(args) > 0 else '' back_color = colorcode.get(str(back_color), '') html = '



