xlsxwriter官方文档,简单易懂。
我的任务是写一个脚本程序,把一个记录“基站测试结果”的txt的内容写到excel中,并在excel中画出折线图。
txt内容如下:
把图中划红线的所有的PHY:RIP和PHY:SF找出来,txt每一行的形式基本是这样:
“ TRACE Warn 2019-08-05 03:01:34.202950 0 27662 [fsmPhyTraceProxy] [20177] [HEX1-smd:WARNING: PHY:RIP[-91,749-1/-69,328-4/-73,338-9/-73]]”
第一步:读入这个txt,按行写成一个列表:
f = open('example.txt', 'r', encoding="utf-8")
content_list = [ i for i in f if 'PHY:RIP' in i ] # 是需要处理的PHY:RIP行,放到content_list里
f.close()
第二步:创建xlsxwriter,并设定一些格式。
注意:xlsxwriter不能对已经存在的excel文件进行读写修改,只能创建一个新的excel。
# xlsxwriter 开始
workbook = xlsxwriter.Workbook('example.xlsx') # 目标是完成一个'example.xlsx'
centered = workbook.add_format({'align': 'center'}) # 写excel的单元格,使用的对齐方式:居中
第三步:给这个excel建立一个sheet。
sheet_PR = workbook.add_worksheet('PHY_RIP') # excel添加一页sheet,命名为PHY_RIP,如果不带'PHY_RIP',会取默认的‘sheet1’。
sheet是指下面这些页码:
第四步:写PHY_RIP上的第一行,每一列的属性标签。
如果不需要属性的这第一行,请忽略这一步。
# 我需要其中13个属性
# “TRACE Warn 2019-08-05 03:01:34.202950 0 27662 [fsmPhyTraceProxy] [20177] [HEX1-smd:WARNING:
# PHY:RIP[-91,749-1/-69,328-4/-73,338-9/-73]]”
# 在sheet_PR中,在(0,0)即第1行第A列,写入数据“DATE”,居中对齐
sheet_PR.write(0, 0, 'DATE', centered) # 日期 2019-08-05
sheet_PR.write(0, 1, 'TIME', centered) #时间到秒 03:01:34
sheet_PR.write(0, 2, 'STAMP', centered) #时间戳 202950
sheet_PR.write(0, 3, 'Average RIP', centered) # 平均RIP值 -91
sheet_PR.write(0, 4, 'The Highest RIP: SFN', centered) # 最高RIP对应的SFN 749
sheet_PR.write(0, 5, 'The Highest RIP: SF', centered) # 最高RIP值对应的SF 1
sheet_PR.write(0, 6, 'The Highest RIP', centered) # 最高RIP -69
sheet_PR.write(0, 7, 'The 2nd Highest RIP: SFN', centered) # 次高RIP对应的SFN 328
sheet_PR.write(0, 8, 'The 2nd Highest RIP: SF', centered) # 次高RIP对应的SF 4
sheet_PR.write(0, 9, 'The 2nd Highest RIP', centered) # 次高RIP -73
sheet_PR.write(0, 10, 'The 3rd Highest RIP: SFN', centered) # 第三高RIP对应的SFN 338
sheet_PR.write(0, 11, 'The 3rd Highest RIP: SF', centered) # 第三高RIP对应的SFN 9
sheet_PR.write(0, 12, 'The 3rd Highest RIP', centered) # 第三高RIP -73
# sheet_PR.write('A13', 'The 3rd Highest RIP', centered) # 第三高RIP -73
# sheet_PR.write_row(0, 0, ['DATE', 'TIME', 'STAMP', 'Average RIP', 'The Highest RIP: SFN', '...'])
# write_row,可以直接写成一行。
效果:第一行属性“DATE TIME STAMP AVERAGE RIP……”
第五步,写下面每一行的单元格
PR= 1 # 用于计“行数”,从第二行(1)开始,因为第一行(0)已经是属性.后面会经常用到这个。
for j in content_list: # content_list是第一步中按行存储txt的list
# 把读出来的每一行按空格split,得到['Trace', 'Warn', ’2019-08-05', '03:01:34.202950', '0', ’27662', '[fsmPhyTraceProxy] [20177] [HEX1-smd:WARNING:', 'Warn', ’PHY:RIP[-91,749-1/-69,328-4/-73,338-9/-73]]' ]
line_list = [i for i in (j.split(' ')) if i != '']
number_list = re.findall(r'[^\d](-?\d+)', line_list[-1]) # findall出-91、749、1、69、328、4、73、338、9、-73
sheet_PR.write(PR, 0, line_list[2], centered) # 2019-08-05 对应DATE
sheet_PR.write(PR, 1, line_list[3][:8], centered) # '03:01:34.202950'的03:01:34 对应TIME
sheet_PR.write(PR, 2, line_list[3][9:], centered) # '03:01:34.202950'的202950 对应STAMP
sheet_PR.write(PR, 3, int(number_list[0]), centered) # -91 0 对应“平均RIP值”
sheet_PR.write(PR, 4, int(number_list[1]), centered) # 749 1 对应“最高RIP对应的SFN”
sheet_PR.write(PR, 5, int(number_list[2]), centered) # 1 2 对应“最高RIP值对应的SF”
sheet_PR.write(PR, 6, int(number_list[3]), centered) # -69 3 对应“最高RIP”
sheet_PR.write(PR, 7, int(number_list[4]), centered) # 328 4 对应“次高RIP对应的SFN”
sheet_PR.write(PR, 8, int(number_list[5]), centered) # 4 5 对应“次高RIP对应的SF”
sheet_PR.write(PR, 9, int(number_list[6]), centered) # -73 6 对应“次高RIP”
sheet_PR.write(PR, 10, int(number_list[7]), centered) # 338 7 对应“第三高RIP对应的SFN”
sheet_PR.write(PR, 11, int(number_list[8]), centered) # 9 8 #对应“第三高RIP对应的SF”
sheet_PR.write(PR, 12, int(number_list[9]), centered) # -73 9 #对应“第三高RIP”
PR += 1 # 每完成一行,PR+1
第六步:画折线图
# 利用第一个sheet中, D列(3)、G列(6)、J列(9)、M列(12)的数据,新建一个chart:DGJM_1
DGJM_1 = workbook.add_chart({'type': 'line'}) # 图类型为折线图
DGJM_1.set_title({'name': 'Average & Top 3 Highest RIP'}) # 图的标题:Average & Top 3 Highest RIP
DGJM_1.set_size({'x_scale': 2, 'y_scale': 2}) # x轴和y轴的每一刻度的大小,设置的越大,你的图就越长越宽
DGJM_1.set_y_axis({'major_unit': 3}) # y轴主要的一个计量单位为3(kg、km、辆、斤)
DGJM_1.add_series({ # 加一条“折线”
'categories': ['PHY_RIP', 1, 1, PR, 1], # 折线在x轴上,用“PHY_RIP”这一sheet中,(第2行,B列)到(第PR+1行,B列)的数据,与之对应
'marker': {'type': 'diamond'}, # 折线的样式,宝石,折点用菱形标记
'name': 'Average RIP', # 折线的名称
'values': ['PHY_RIP', 1, 3, PR, 3], # 折线在y轴上的值,用“PHY_RIP”这一sheet中,(第2行,D列)到(第PR+1行,D列)的数据,与之对应。
# values必须声明,其他设置可以默认。
})
DGJM_1.add_series({ # 加第二条折线,G列
'categories': ['PHY_RIP', 1, 1, PR, 1],
'marker': {'type': 'diamond'},
'name': 'The Highest RIP',
'values': ['PHY_RIP', 1, 6, PR, 6],
})
DGJM_1.add_series({ # 加第三条折线,J列
'categories': ['PHY_RIP', 1, 1, PR, 1],
'marker': {'type': 'diamond'},
'name': 'The 2nd Highest RIP',
'values': ['PHY_RIP', 1, 9, PR, 9],
})
DGJM_1.add_series({ # 加第四条折线,M列
'categories': ['PHY_RIP', 1, 1, PR, 1],
'marker': {'type': 'diamond'},
'name': 'The 3rd Highest RIP',
'values': ['PHY_RIP', 1, 12, PR, 12],
})
# sheet_PR.insert_chart('A32', DGJM_1) # 把DGJM_1这个折线图放到sheet_PR这一页里,图的左上角起始位置是“A32”
# sheet_PR.insert_chart(31, 0, DGJM_1) # 图的左上角起始位置是“A32”
sheet_PR.insert_chart('A' + str(PR+3), DGJM_1) # 在sheet_PR上嵌入这个图,图的左上角在第A列第(PR+3)行上。
效果:
第六步:完成,close。
workbook.close() # 保存xlsx文件
其他问题:
1、xlsxwriter不能读写已经存在的excel,必须完全创造一个新的excel文件。
2、代码中有很多针对我这个txt,采取的繁琐的、获取数据的方法,可以跳过他们,xlsxwriter主要的方法就几个:add、write、insert、close等。
3、write完数据后,想按某一列数据重新排序,似乎没有方法。给我的感觉是,xlsxwriter还是要我“手动“操作每一个单元格的内容,这个txt实际上我处理了18种“行”、200种“元素”、150张图,写到崩溃。
4、画折线图的x轴。x轴是用的“时间”那一列,但仔细看图就会发现,x轴实际上是条形图的那种——一个刻度表示那一秒,而不是x轴上一个点表示那一秒。如果要设置成真正的时间轴或者其他值类型的轴,有设置x轴起始自min,结束于max的方法,详细请看官方文档。
6、画折线图的y轴。如果不设置“DGJM_1.set_y_axis({‘major_unit’: 3}) ”精度为3的话,一旦数值波动很小,y轴就会出现"小数"精度。
7、在哪个单元格写数据,有“A32”“31, 0”两种写法。
8、其他设置请看官方文档,比如图的背景,用扇形图等。