先看代码:定义一个HandleExcel类,初始化方法打开一个工作簿并赋值实例属性workbook、sheet等,其他的读取excel数据的方法暂时没有写上,本文旨在保存数据上做详解。
class HandleExcel(object):
"""
对excel操作的封装,读取/写入数据,以及删除sheet表等,
默认是对Sheet表进行操作
"""
def __init__(self,filename:str,sheetname:str='Sheet1') -> None:
"""
初始化读取对象
:param filename:文件名字
:param sheetname:sheet表单名
"""
logger.info(f'读取excle文件 {filename} 的 {sheetname} sheet表单')
#打开工作簿
self.workbook=openpyxl.load_workbook(filename)
#选择sheet表单
self.sheet=self.workbook[sheetname]
#定义实例属性
self.filename=filename
# super().__init__()
#获取excel的最大行
self.max_rows=self.sheet.max_row
#写入数据
def sava_excel_data(self,cloumn:None,row:int,value:any)->None:
"""
存储数据到excel
:param cloumn:列,数字或者英文字母
:param row:行
:param value:存储数据
"""
#判断是根据列名还是列数写入数据
try:
if isinstance(cloumn,int):
self.sheet.cell(row,cloumn,value)
else:
self.sheet['{}{}'.format(cloumn,row)].value=value
except BaseException as msg:
print(f'请勿打开需要写入数据的excel文件:{msg}')
else:
self.workbook.save(self.filename)
self.workbook.close()
以上方法在项目的大多数情况下都能写入数据并使脚本正常运行,但是在遇到一个excel中存在多个sheet表单时,每一个表单都作为一个实例对象,确实也可以读取每一个表单的数据。但是如果要修改每一个表单或者多个表单时,每一个实例对象仅仅能修改自己的表单,并不能再这个实例对象下修改别的表单,说白了就是如下代码并不能安装我的意愿修改我想要的表单数据:理论上来说,register_data这个实例对象在调用sava_excel_data方法时,保存了数据;等到下一个实例对象kyc_data来调用sava_excel_data方法时,也保存了数据。两个sheet表单的数据应该都修改了才对
register_data = HandleExcel(os.path.join(SystemEnv.DATA_DIR,'testcases.xlsx'),'gm_register')
kyc_data = HandleExcel(os.path.join(SystemEnv.DATA_DIR,'testcases.xlsx'),'gm_kyc')
register_data.sava_excel_data('J',2,'63456485456')
kyc_data.sava_excel_data('J',2,'U9998747')
但是事实并非如此:gm_register的表单并没有成功保存数据!
但是gm_kyc表单成功保存了数据:
同样是写入J2单元格的内容,只有后面这个对象成功保存了数据。
当然,这种方法同样可以实现我的需求:一个实例对象,保存一次数据,下个实例对象再保存一次
register_data = HandleExcel(os.path.join(SystemEnv.DATA_DIR,'testcases.xlsx'),'gm_register')
register_data.sava_excel_data('J',2,'63456485456')
kyc_data = HandleExcel(os.path.join(SystemEnv.DATA_DIR,'testcases.xlsx'),'gm_kyc')
kyc_data.sava_excel_data('J',2,'U9998747')
但是这种做法很鸡肋,因为在脚本中保存的数据很多,不可能每次都是实例化后保存再实例化另外一个表单保存。因为这里workbook整个工作表作为的是一个实例属性,是每个表单私有的属性:self.workbook=openpyxl.load_workbook(filename)
这种写法注定只能一个实例对象操作一个workbook对象,修改整个工作表。
那么有没有什么办法是所有实例对象都能操作这个workbook对象呢?
有!直接将workbook作为类对象,每个实例对都能访问和更改他的属性:
class HandleExcel(object):
workbook = None
"""
对excel操作的封装,读取/写入数据,以及删除sheet表等,
默认是对Sheet表进行操作
"""
def __init__(self,filename:str,sheetname:str='Sheet1') -> None:
"""
初始化读取对象
:param filename:文件名字
:param sheetname:sheet表单名
"""
if not HandleExcel.workbook:
HandleExcel.workbook = openpyxl.load_workbook(filename)
#打开工作簿
#选择sheet表单
self.sheet=HandleExcel.workbook[sheetname]
#定义实例属性
self.filename=filename
self.sheetname =sheetname
# super().__init__()
#获取excel的最大行
self.max_rows=self.sheet.max_row
#写入数据
def sava_excel_data(self,cloumn:None,row:int,value:any)->None:
"""
存储数据到excel
:param cloumn:列,数字或者英文字母
:param row:行
:param value:存储数据
"""
logger.info(f'写入{self.filename}文件 {self.sheetname} 表单 {cloumn} 列{row} 行:{value}')
#判断是根据列名还是列数写入数据
try:
if isinstance(cloumn,int):
self.sheet.cell(row,cloumn,value)
else:
self.sheet['{}{}'.format(cloumn,row)].value=value
except BaseException as msg:
print(f'请勿打开需要写入数据的excel文件:{msg}')
else:
HandleExcel.workbook.save(self.filename)
HandleExcel.workbook.close()
概念上讲: