openpyxl写入xlsx报错:'WriteOnlyWorksheet'对象无cell属性
问题现象
使用openpyxl库编写Python脚本写入xlsx文件时,在单元格赋值行抛出如下异常:
AttributeError: 'WriteOnlyWorksheet' object has no attribute 'cell'
运行时打印的相关变量值如下:
titulo: checkalllfromdatesbiggerthannumber xp: [40.0, 39.0, 42.0, 39.0, 24.0, 22.0, 9.0] xp1: [1143.0, 1278.0, 1157.0, 1115.0, 617.0, 484.0, 241.0] yp: ['2021-11-08', '2021-11-09', '2021-11-10', '2021-11-11', '2021-11-12', '2021-11-13', '2021-11-14']
出问题的原始功能函数代码:
def faz_fich_excell(titulo,xp,xp1,yp): print("titulo: ", titulo) print('xp: ', xp) print('xp1: ', xp1) print('yp: ', yp) ficheiro = "teste_a.xlsx" ayp = list(yp) axp = list(xp) axp1 = list(xp1) titulo = titulo[:30] if not os.path.exists(ficheiro): wb = openpyxl.Workbook() for x in wb.get_sheet_names(): std = wb.get_sheet_by_name(x) wb.remove_sheet(std) else: os.chmod(os.path.join(ficheiro), 0o777) wb = openpyxl.Workbook(ficheiro) wb.create_sheet(titulo.replace(" ", "")) ws = wb[titulo.replace(" ", "")] ws = wb.active r=1 for y,x,z in zip(ayp,axp,axp1): print(y,x,z) ws.cell(row=r, column=1).value = str(y) ws.cell(row=r, column=2).value = str(x) ws.cell(row=r, column=3).value = str(z) r += 1 wb.save(os.path.join(ficheiro))
错误根因
- 核心触发原因:工作簿打开方式错误。
openpyxl.Workbook()是创建新空白工作簿的构造方法,第一个位置参数是write_only(只写模式开关,默认False),不能用来打开已有文件。代码中在文件已存在的分支里写wb = openpyxl.Workbook(ficheiro),传入的文件路径会被当做write_only参数值,非空字符串判定为布尔真,因此自动开启了只写工作簿模式。该模式下生成的工作表是WriteOnlyWorksheet类型,不支持.cell()方法随机读写单元格,仅支持append()逐行追加写入,因此调用.cell()时直接抛出属性不存在的错误。打开已有xlsx文件的正确方法是使用openpyxl.load_workbook()。 - 次要逻辑错误:工作表引用被覆盖。代码中先通过名称获取了刚创建的自定义工作表,紧接着执行
ws = wb.active将变量重新指向工作簿默认激活的工作表,前面的自定义表引用完全失效,在只写模式场景下刚好拿到了不支持.cell()方法的WriteOnlyWorksheet对象。 - 兼容隐患:使用已废弃API。代码中调用的
get_sheet_names()、get_sheet_by_name()、remove_sheet()都是openpyxl早期版本的API,在新版本中已被标记废弃,容易出现兼容问题。
修复方案
按以下规则修改代码即可解决问题:
- 已有文件加载统一使用
openpyxl.load_workbook(),禁止给Workbook()构造函数传入文件路径 - 删除多余的
ws = wb.active赋值,直接使用自定义名称的工作表对象 - 替换所有废弃API:获取所有工作表用
wb.sheetnames,删除工作表用wb.remove(worksheet) - 调整工作表创建逻辑:新建工作簿时不需要先删默认表再建新表,可以直接修改默认表的名称,减少冗余操作;增加重名工作表判断,避免重复运行时报错
修复后的完整代码:
import os import openpyxl def faz_fich_excell(titulo,xp,xp1,yp): print("titulo: ", titulo) print('xp: ', xp) print('xp1: ', xp1) print('yp: ', yp) ficheiro = "teste_a.xlsx" sheet_name = titulo[:30].replace(" ", "") ayp = list(yp) axp = list(xp) axp1 = list(xp1) if not os.path.exists(ficheiro): wb = openpyxl.Workbook() # 直接修改默认工作表名称,不需要删了再建 ws = wb.active ws.title = sheet_name else: os.chmod(ficheiro, 0o777) # 正确加载已有工作簿 wb = openpyxl.load_workbook(ficheiro) # 如果同名工作表已存在先删除,避免创建报错 if sheet_name in wb.sheetnames: del wb[sheet_name] ws = wb.create_sheet(sheet_name) r=1 for y,x,z in zip(ayp,axp,axp1): print(y,x,z) ws.cell(row=r, column=1).value = str(y) ws.cell(row=r, column=2).value = str(x) ws.cell(row=r, column=3).value = str(z) r += 1 wb.save(ficheiro) wb.close()
内容的提问来源于stack exchange,提问作者PyGood
相关产品推荐
相关产品推荐

