openpyxl保存Excel报NoneType无read属性 求非清空注释解决方案
报错根本原因
该错误是openpyxl处理包含VBA宏、旧格式Excel遗留批注的工作簿时触发的,常见于打开带宏的xlsm文件后另存为xlsx格式,或者工作簿内存在未被正确识别的旧版批注,以下是无需修改sheet._comments私有属性的解决方案:
可行解决方案
方案1:适配带宏文件的读写规则
如果你操作的原文件是带宏的xlsm格式,不要强行保存为xlsx格式,打开工作簿时添加keep_vba=True参数,保存时后缀使用.xlsm即可:# 打开文件时指定保留VBA self.output_excel = openpyxl.load_workbook("源文件.xlsm", keep_vba=True) # 保存时使用xlsm后缀 output_excel_path = self.output_name + ".xlsm" self.output_excel.save(output_excel_path)方案2:迁移数据到全新工作簿后保存
不修改原工作簿对象,新建空白工作簿后把原工作簿的所有内容(数值、格式、公式等)复制到新工作簿,彻底避免旧工作簿的残留属性触发bug:from openpyxl import Workbook # 新建空白工作簿 new_wb = Workbook() # 删除默认生成的空白Sheet new_wb.remove(new_wb.active) # 遍历原工作簿所有Sheet for ws in self.output_excel.worksheets: new_ws = new_wb.create_sheet(ws.title) # 复制单元格内容和格式 for row in ws.iter_rows(): for cell in row: new_cell = new_ws[cell.coordinate] new_cell.value = cell.value # 可选:保留单元格样式可以打开下方注释 # if cell.has_style: # new_cell.font = cell.font # new_cell.border = cell.border # new_cell.fill = cell.fill # new_cell.number_format = cell.number_format # new_cell.protection = cell.protection # new_cell.alignment = cell.alignment # 复制列宽 for col in ws.column_dimensions: new_ws.column_dimensions[col].width = ws.column_dimensions[col].width # 复制行高 for row in ws.row_dimensions: new_ws.row_dimensions[row].height = ws.row_dimensions[row].height # 保存新工作簿 new_wb.save(output_excel_path)方案3:替换Excel操作库
不想适配openpyxl的bug可以换用兼容性更高的库完成保存操作:- 仅需要保留数据和基础格式可以使用pandas输出:
import pandas as pd with pd.ExcelWriter(output_excel_path) as writer: for ws in self.output_excel.worksheets: df = pd.DataFrame(ws.values) df.to_excel(writer, sheet_name=ws.title, index=False, header=False)- 需要完整保留所有格式、宏、批注可以使用xlwings调用本地Excel程序完成操作(需要设备安装Excel):
import xlwings as xw app = xw.App(visible=False) wb = app.books.open("源文件路径") # 此处添加你的文件修改逻辑 wb.save(output_excel_path) wb.close() app.quit()
内容的提问来源于stack exchange,提问作者Sultry T.
相关产品推荐
相关产品推荐

