简介
本博文案例场景为使用python3通过调用xlrd、xlwt模块编写脚本,实现对excel进行处理,其中涉及行列转换、合并单元格。
背景
在一次工作中,需要统计日志监控平台对哪些系统、哪些IP、哪些路径进行了日志监控。这些数据存在于mysql的一张表中,当把数据从mysql导出到excel后,发现excel的数据格式不太满意,还需要对excel的格式做些调整。为了更直观,我将导出后的数据格式和期待的格式截图并展示。
-
导出后的格式
-
期待的格式
思路
那么该如何将导出后源文件的格式调整为期待的格式呢?我的思路是:
- 将源文件中的数据逐行写入到列表Ret中,如下
[['系统名称', '日志路径', 'IP'],
['ZBX', '/home/zbx/logs/*.log', '192.168.1.10'],
['ZBX', '/home/zbx/logs/*.log', '192.168.1.11'],
['ELK', '/home/elk/logs/*.log', '192.168.1.20'],
['ELK', '/home/elk/logs/*.log', '192.168.1.21'],
['ELK', '/home/elk/logs/*.log', '192.168.1.22'],
['ELK', '/home/elk/logs/*.log', '192.168.1.23'],
['ELK', '/home/elk/logs/*.log', '192.168.1.24'],
['ELK', '/home/elk/logs/*.log', '192.168.1.25'],
['Nginx', '/home/nginx/logs/*.log', '192.168.1.30'],
['Nginx', '/home/nginx/logs/*.log', '192.168.1.31'],
['Nginx', '/home/nginx/logs/*.log', '192.168.1.32'],
['Nginx', '/home/nginx/logs/*.log', '192.168.1.33'],
['Tomcat', '/home/tomcat/logs/*.log', '192.168.1.40'],
['Tomcat', '/home/tomcat/logs/*.log', '192.168.1.41'],
['Tomcat', '/home/tomcat/logs/*.log', '192.168.1.42'],
['Tomcat', '/home/tomcat/logs/*.log', '192.168.1.43'],
['Tomcat', '/home/tomcat/logs/*.log', '192.168.1.44'],
['Tomcat', '/home/tomcat/logs/*.log', '192.168.1.45'],
['Tomcat', '/home/tomcat/logs/*.log', '192.168.1.46'],
['Tomcat', '/home/tomcat/logs/*.log', '192.168.1.47']]
- 将列表中Ret相同系统名称的首行元素的索引追加到列表Idx,Idx初始化时为[0],追加后如下
[0, 1, 3, 9, 13, 21]
- 通过列表Idx中的值,可以推断每列需要合并单元格的起始位置和结束为止,然后合并
- 将IP以此写在新文件的第四列中
代码
# -*- coding:utf-8 -*-
import os
import sys
import xlrd,xlwt
work_dir = os.path.dirname(os.path.abspath(sys.argv[0]))
r_xls = os.path.join(work_dir,sys.argv[1])
d_xls = os.path.join(work_dir,'result.xls')
def DataByLine(Line,ret,idx):
# 读取xls数据,按照需求生成列表
# idx是列表,通过源文件中系统的IP个数推断出在新文件中这个系统的末行数据的行索引
# ret是列表,用于存放xls中的数据
t = idx[-1]
while '' in Line:
Line.remove('')
# 从源文件中逐行读取的数据是列表格式,其中会存在空值,需要将空值删除
for i in range(2,len(Line)):
# 遍历IP,组成有系统、路径、ip元素的列表
ret.append([Line[0],Line[1],Line[i]])
t += 1
idx.append(t)
return ret,idx
# 将列表中的数据,依次写入新的xls
def WtData(workbook,table,ret,idx,xls):
for i,j in enumerate(idx):
if (i+1) < (len(idx)):
# 避免idx中最后一个元素参与下面的,最后一个元素代表的是整个表格数据的末行索引
table.write_merge(j,idx[i+1]-1,0,0,ret[j][0])
# 对第一列(相同系统)同样的系统进行合并单元格
table.write_merge(j,idx[i+1]-1,1,1,ret[j][1])
# 对第二列(相同路径)同样的系统进行合并单元格
for k in range(idx[i+1]-idx[i]):
table.write(idx[i]+k,2,ret[j+k][2])
# 将按行显示的IP,在第三列转置后,按列存储
workbook.save(xls)
def main():
workbook_r = xlrd.open_workbook(r_xls)
table_r = workbook_r.sheet_by_index(0)
workbook_d = xlwt.Workbook(encoding = 'utf-8')
table_d = workbook_d.add_sheet('result')
Nrow = table_r.nrows
Ret = []
Idx = [0]
for ln in range(Nrow):
Ret,Idx = DataByLine(table_r.row_values(ln),Ret,Idx)
WtData(workbook_d,table_d,Ret,Idx,d_xls)
if __name__ == '__main__':
main()
验证
[root@pyenv xls_format]# /opt/soft/python374/bin/python3 xls_format.py logs.xls
输出文件内容如下: