
xlwings 默认的 .note 属性无法读取受密码保护工作表中的批注,需通过底层 COM 接口(.api.Comment.Text())访问;本文详解两种可靠方法:单单元格批注提取与全工作簿批量遍历。
xlwings 默认的 `.note` 属性无法读取受密码保护工作表中的批注,需通过底层 com 接口(`.api.comment.text()`)访问;本文详解两种可靠方法:单单元格批注提取与全工作簿批量遍历。
在使用 xlwings 操作受密码保护的 Excel 文件时,一个常见误区是直接调用 range.note 获取批注——该属性在工作表受保护状态下始终返回 None,即使单元格实际存在批注。这是因为 .note 是 xlwings 封装的轻量级只读属性,不穿透 Excel 的保护层;而真正的批注对象需通过底层 COM 接口(Windows 平台下由 pywin32 驱动)访问。
✅ 正确做法是使用 .api.Comment.Text() 方法(注意大小写和括号),它直接调用 Excel Application 对象的原生 API,可绕过保护限制(前提是已成功以密码打开工作簿)。以下为推荐代码:
import xlwings as xw
PATH = r'C:/Users/Hendo/Pictures/Sample.xlsx'
psw = '1234'
wb = xw.Book(PATH, password=psw)
sheet = wb.sheets['Sheet1']
# ✅ 正确:通过 COM 接口读取批注文本
try:
comment_text = sheet.range('H15').api.Comment.Text()
print("批注内容:", comment_text)
except AttributeError:
print("H15 单元格无批注")
print("单元格值:", sheet.range('H15').value)
⚠️ 注意事项:
- 仅适用于 Windows + Excel 桌面版(依赖 COM);
- 必须确保 Excel 已安装且 xlwings 后端为 app(默认);
- 若单元格无批注,.api.Comment 会抛出 AttributeError,务必用 try/except 捕获;
- .api.Comment.Text() 返回纯字符串;若需作者、时间等元信息,应访问 cmt.Author、cmt.Date 等属性(见批量方案)。
? 批量提取全工作簿所有批注(含位置、作者、内容):
import xlwings as xw
excel_file = r'C:/Users/Hendo/Pictures/Sample.xlsx'
with xw.App(visible=False) as app:
wb = xw.Book(excel_file, password='1234') # ⚠️ 密码必须传入此处!
for sheet in wb.sheets:
print(f"---- 工作表 '{sheet.name}' ----")
# 遍历该表所有 Comment 对象(非空批注)
if sheet.api.Comments.Count > 0:
for cmt in sheet.api.Comments:
addr = cmt.Parent.Address.replace('$', '') # 如 'H15'
try:
text = cmt.Text()
author = cmt.Author
print(f"? 单元格: {addr}")
print(f"? 作者: {author}")
print(f"? 内容: {text}")
print("-" * 40)
except Exception as e:
print(f"[警告] 读取 {addr} 批注失败: {e}")
else:
print("→ 本工作表无批注")
wb.close()
? 总结:
- ❌ 避免使用 range.note 处理受保护工作表的批注;
- ✅ 坚持使用 .api.Comment.Text() 并配合异常处理;
- ? 密码必须在 xw.Book(..., password=...) 中传入,否则 API 调用将失败;
- ? 批量场景建议关闭 visible=True 并显式 close() 工作簿,避免后台 Excel 进程残留。











