一、需求
公司要求把从16年1月1日到当前的所有处理事件合并 ,简单的理解就是把所有的日报合并到一个表格中呗。刚好16所有的日报都保留在一个文件夹中了,这里通过python + xlrd(读) + xlsxwriter(写) 实现把所有的日志汇总到一个excel 文件中 。这里没有用xlwt模块进行写操作,由于目前主流使用的office基本都2007以后的了,所以xlsxwriter支持相对更好些。
原日报的格式如下:
需要汇总如下格式
二、python实现
先上代码:
[root@361way ~]# cat python/excel/date_report.py
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# site: www.361way.com
# mail: itybku@139.com
import sys
reload(sys)
sys.setdefaultencoding('utf-8')
import glob
import xlrd
import xlsxwriter
import re
workbook = xlsxwriter.Workbook('date_report.xlsx')
worksheet = workbook.add_worksheet('Sheet1')
bold = workbook.add_format({'bold': 1})
headings = [u'时间', u'问题描述', u'责任人']
worksheet.write_row('A1', headings, bold)
def get_xlsx_data(file):
#data = xlrd.open_workbook(u"D:\\2016\\杭州软件服务部管理服务工作日报(2016-07-13).xlsx")
data = xlrd.open_workbook(file)
table = data.sheets()[0]
nrows = table.nrows
ncols = table.ncols
timedata = table.row_values(0)[0]
timedata = re.split('(',timedata.encode("utf-8",'ignore'))
timedata = timedata[1].replace(')','')
#print timedata
for i in range(7,nrows):
#print table.row_values(i)[0]
if table.row_values(i)[0] == 1.0:
maxv = i
#print maxv
if maxv:
for i in range(6,(maxv-2)):
if table.row_values(i)[2]:
#print timedata + '|' + table.row_values(i)[2].encode("utf-8",'ignore')
data_arry.append([timedata,table.row_values(i)[2].encode("utf-8",'ignore'),'361way'])
else:
for i in range(6,nrows):
if table.row_values(i)[2]:
#print timedata + '|' + table.row_values(i)[2].encode("utf-8",'ignore')
data_arry.append([timedata,table.row_values(i)[2].encode("utf-8",'ignore'),'361way'])
data_arry = []
for file in glob.glob("d:\\2016\\*.xlsx"):
get_xlsx_data(file)
row = 1
col = 0
for linev in data_arry:
#print linev
worksheet.write_row(row,col,linev)
row += 1
workbook.close()
代码比较简单,不过有几个地方可以提提:
1、遍历某个目录下的所有文件,这里用的glob模块,其内部也是通过os.path,isdir之类的代码实现的,实用起来相当便捷;
2、写excel 这里使用的是以行的方式进行写入,对于数据量比较少的,通过行、列写入都无所谓,比如,列数据有几十万条以上的,就不建议再通过list写入列的方式了 --- 比较耗内存,这时候建议将结果先写入文件本,再逐行读取、逐条写入 。按列写入官方的示例如下:
data = [
[2, 3, 4, 5, 6, 7],
[10, 40, 50, 20, 10, 50],
[30, 60, 70, 50, 40, 30],
]
worksheet.write_row('A1', headings, bold)
worksheet.write_column('A2', data[0])
worksheet.write_column('B2', data[1])
worksheet.write_column('C2', data[2])
这里是通过A1、B2这样的方法写入的,如果按坐标写入的方式,逐行写时,列用0表示不能少,可以看我代码中的worksheet.write_row(row,col,linev)。
3、标题上取日期这个,使用的re模块进行的切割,也可以通过re匹配一次获得,当然也可以按普通的切分字符串的方法切分,只不过代码要多些,类似如下:
timedata = table.row_values(0)[0]
timedata = timedata.splitlines()[1]
timedata = timedata.replace('(','')
timedata = timedata.replace(')','')
中间maxv那段主要是为了将明日计划部分去掉,避免和下一日的日报有重复。写的感觉有点重复,也可以函数化调用,懒得改了,代码太简单 。