一、需求

公司要求把从16年1月1日到当前的所有处理事件合并 ,简单的理解就是把所有的日报合并到一个表格中呗。刚好16所有的日报都保留在一个文件夹中了,这里通过python + xlrd(读) + xlsxwriter(写) 实现把所有的日志汇总到一个excel 文件中 。这里没有用xlwt模块进行写操作,由于目前主流使用的office基本都2007以后的了,所以xlsxwriter支持相对更好些。

原日报的格式如下:

xls_report
xls_report

需要汇总如下格式

python-xlsx-report
python-xlsx-report

二、python实现

先上代码:

 1[root@361way ~]# cat python/excel/date_report.py
 2#!/usr/bin/env python
 3# -*- coding: utf-8 -*-
 4# site: www.361way.com
 5# mail: itybku@139.com
 6import sys
 7reload(sys)
 8sys.setdefaultencoding('utf-8')
 9import glob
10import xlrd
11import xlsxwriter
12import re
13workbook = xlsxwriter.Workbook('date_report.xlsx')
14worksheet = workbook.add_worksheet('Sheet1')
15bold = workbook.add_format({'bold': 1})
16headings = [u'时间', u'问题描述', u'责任人']
17worksheet.write_row('A1', headings, bold)
18def get_xlsx_data(file):
19    #data = xlrd.open_workbook(u"D:\\2016\\杭州软件服务部管理服务工作日报(2016-07-13).xlsx")
20    data = xlrd.open_workbook(file)
21    table = data.sheets()[0]
22    nrows = table.nrows
23    ncols = table.ncols
24    timedata = table.row_values(0)[0]
25    timedata = re.split('(',timedata.encode("utf-8",'ignore'))
26    timedata = timedata[1].replace(')','')
27    #print timedata
28    for i in range(7,nrows):
29        #print table.row_values(i)[0]
30        if  table.row_values(i)[0] == 1.0:
31            maxv = i
32    #print maxv
33    if maxv:
34        for i in range(6,(maxv-2)):
35            if  table.row_values(i)[2]:
36                #print timedata + '|' + table.row_values(i)[2].encode("utf-8",'ignore')
37                data_arry.append([timedata,table.row_values(i)[2].encode("utf-8",'ignore'),'361way'])
38    else:
39        for i in range(6,nrows):
40            if  table.row_values(i)[2]:
41                #print timedata + '|' + table.row_values(i)[2].encode("utf-8",'ignore')
42                data_arry.append([timedata,table.row_values(i)[2].encode("utf-8",'ignore'),'361way'])
43data_arry = []
44for file in glob.glob("d:\\2016\\*.xlsx"):
45    get_xlsx_data(file)
46row = 1
47col = 0
48for linev in  data_arry:
49    #print linev
50    worksheet.write_row(row,col,linev)
51    row += 1
52workbook.close()

代码比较简单,不过有几个地方可以提提:

1、遍历某个目录下的所有文件,这里用的glob模块,其内部也是通过os.path,isdir之类的代码实现的,实用起来相当便捷;

2、写excel 这里使用的是以行的方式进行写入,对于数据量比较少的,通过行、列写入都无所谓,比如,列数据有几十万条以上的,就不建议再通过list写入列的方式了 --- 比较耗内存,这时候建议将结果先写入文件本,再逐行读取、逐条写入 。按列写入官方的示例如下:

1data = [
2    [2, 3, 4, 5, 6, 7],
3    [10, 40, 50, 20, 10, 50],
4    [30, 60, 70, 50, 40, 30],
5]
6worksheet.write_row('A1', headings, bold)
7worksheet.write_column('A2', data[0])
8worksheet.write_column('B2', data[1])
9worksheet.write_column('C2', data[2])

这里是通过A1、B2这样的方法写入的,如果按坐标写入的方式,逐行写时,列用0表示不能少,可以看我代码中的worksheet.write_row(row,col,linev)。

3、标题上取日期这个,使用的re模块进行的切割,也可以通过re匹配一次获得,当然也可以按普通的切分字符串的方法切分,只不过代码要多些,类似如下:

1timedata = table.row_values(0)[0]
2timedata = timedata.splitlines()[1]
3timedata = timedata.replace('(','')
4timedata = timedata.replace(')','')

中间maxv那段主要是为了将明日计划部分去掉,避免和下一日的日报有重复。写的感觉有点重复,也可以函数化调用,懒得改了,代码太简单 。