xlrd读取excel工具类
代码特色: 不用下标去匹配列,采用正则匹配,这样就不用关心excel模板中列的位置而获取想要的信息
用于读取大量模板类似但是列顺序不一样的excel
一. 工具类代码
# 工具类
import xlrd
import re
from datetime import datetime
from xlrd import xldate_as_tuple
class ExcelExport:
"""
本类是读取excel的工具类,封装了读取excel常用的方法,主要借助xlrd的方法
"""
def __init__(self, file):
"""
类的初始化方法
:param file: excel文件路径
"""
self.wookbook = xlrd.open_workbook(file)
self.__start_row = 0
self.__excel_titles = []
def set_sheet(self, index):
"""
设置操作sheet,保存到属性sheet中
:param index: sheet的下表,为不小于0的整数
:return:
"""
self.sheet = self.wookbook.sheet_by_index(index)
def get_start_row(self, reg):
"""
获取开始的行,即表头开始的行
:param reg: 表头所在行中某一个特有的列的正则,例如表头为['标称生产企业','生产日期'],reg即为'^标称生产'
:return:返回开始行
"""
for curr_row in range(self.sheet.nrows):
for curr_col in range(self.sheet.ncols):
if re.search(reg, str(self.sheet.cell_value(curr_row,curr_col))):
self.__start_row = curr_row
break
return self.__start_row
def get_excel_titles(self, reg):
"""
获取excel表头list
:param reg: 表头所在行中某一个特有的列的正则,例如表头为['标称生产企业','生产日期'],reg即为'^标称生产'
:return: 表头list
"""
if self.__start_row == 0:
self.get_start_row(reg)
self.__excel_titles = self.sheet.row_values(self.__start_row)
return self.__excel_titles
def __format_date(self, cell):
"""
格式化日期
:param cell: excel某一cell类型的格子
:return: 返回格式化好的日期
"""
type = cell.ctype
rq = ''
# 如果是日期类型
if type == 3:
date = datetime(*xldate_as_tuple(cell.value, 0))
rq = date.strftime('%Y-%m-%d')
# 如果是字符串
elif type == 1:
rq = cell.value.replace('.', '-')
# 如果是数字
elif type == 2:
rq = self.parse(cell.value, '-')
return rq
def parse(self, num, split):
"""
将数字转换为日期格式字符串,例如 20181019用-转换为: 2018-10-19
:param num: num需要转换的数字
:param split: 分隔符
:return: 转换后的字符串
"""
str1 = str(int(num))
if len(str1) == 8:
new_str = str1[0:4] + split + str1[4:6] + split + str1[6:]
else:
new_str = str1
return new_str
def get_one_data(self, excel_titles, data, curr_row, date_data = None):
"""
根据正则获取一行数据
:param exce_titles: excel表头list
:param data:正则格式字典,key为需要保存的变量字符串,value为正则表达式,例如{'cybh':'样编'},得到的数据为cybh = excel对应的数据
:param curr_row:需要获取数据的行
:param date_data: 日期格式的数据list,默认为None,如果excel中有日期格式的数据,将变量名称保存为list,例如['scrq','ggrq']
:return: 返回行数据字典
"""
detail = {}
if date_data == None:
for i in excel_titles:
for e in data.items():
if re.search(e[1], str(i)):
str1 = 'detail["%s"]="%s"' % (e[0],self.sheet.cell_value(curr_row, excel_titles.index(i)))
exec(str1)
for d in data:
if not detail.get(d):
detail[d] = ''
else:
for i in excel_titles:
for e in data.items():
if re.search(e[1], str(i)):
if not e[0] in date_data:
str1 = 'detail["%s"]="%s"' % (e[0],self.sheet.cell_value(curr_row, excel_titles.index(i)))
exec(str1)
else:
rq = self.__format_date(self.sheet.cell(curr_row, excel_titles.index(i)))
str1 = 'detail["%s"]="%s"' % (e[0], rq)
exec(str1)
for d in data:
if not detail.get(d):
detail[d] = ''
return detail
二. 测试代码
from inspection.utils import ExcelExport
excel = ExcelExport('F:/gov_1542056901814.xls')
excel.set_sheet(0)
excel_titles = excel.get_excel_titles('^标称生产')
data = {'cybh':'样编','num':'序号','bcscqymc':'生产企业名称','bcscqydz':'生产企业地址','bcydwmc':'被抽样单位名称'
,'bcydwdz':'被抽样单位地址','spmc':'品名','ggxh':'格型','sb':'商标','bzz':'标准值','jcjg':'检验结果'
,'bhdxm':'不合格项目','jyjg':'检验机构','fl':'分类','ggh':'公告号','rwly':'任务来源','bz':'备注'
,'bcydwszsf':'被抽样单位所在省份','spxl':'食品细类','scrq':'生产日期'}
start_row = excel.get_start_row('^标称生产')
for curr_row in range(start_row + 1, excel.sheet.nrows):
detail = excel.get_one_data(excel_titles,data,curr_row,date_data=['scrq'])
print(detail)