You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

VBA错误91:工作表保护场景下Intersect返回Nothing问题求助

VBA 错误91(Intersect返回Nothing)问题修复

问题现象

  • 代码绑定在Worksheet_Change(ByVal Target As Range)事件下执行,运行时同步打开2个用户窗体,全程未使用ActiveSheet类易产生歧义的相对引用语句。
  • 触发规律:工作表初始为未保护状态时代码运行完全正常;一旦通过宏代码或手动开启工作表保护,即使后续执行取消保护操作,代码自动运行时就会抛出错误91;逐行按F8调试模式下代码可正常运行,添加Wait等待语句无法解决问题。
  • 报错定位:报错行是Intersect(targetRow, rgRecName) = foundName,经确认三个关联变量均能正常读取有效值:targetRow为整行范围对象、rgRecName为列范围对象、foundName为字符串类型,但Intersect(targetRow, rgRecName)返回值始终为Nothing。

关联代码片段

主执行逻辑

.......
Application.EnableEvents = False 
PrUpr.UJournal '工作表保护相关逻辑存放在PrUpr模块
Intersect(targetRow, rgRecName) = foundName '!! 报错触发位置 !!
.......
PrUpr.PJournal
.......

工作表取消保护逻辑(PrUpr模块内)

Sub UJournal()
 ThisWorkbook.Worksheets("Journal").Unprotect "123"
End Sub

工作表加保护逻辑(PrUpr模块内)

Sub PJournal()
 With ThisWorkbook.Worksheets("Journal")
   .Protect Password:="123", UserInterfaceOnly:=True, AllowFormattingCells:=True, 
    AllowFormattingColumns:=True, AllowFormattingRows:=True, AllowSorting:=False, 
    AllowFiltering:=True, AllowDeletingRows:=True
   .EnableSelection = xlNoRestrictions
 End With
End Sub

已排查无效的方案

  • 切换UserInterfaceOnly:=True / False参数
  • 确认Workbook_Open事件中无保护相关逻辑
  • 调整全表单元格的锁定/解锁状态

根因说明

这类「逐行调试正常、全速运行报错,加Wait也无效」的Intersect返回Nothing问题,核心原因是传入Intersect的两个Range对象内部父句柄不一致:
工作表执行保护/取消保护操作时,会刷新自身的Range对象实例索引。全速运行时VBA不会等待实例索引刷新完成,之前定义的targetRow、rgRecName还保留着操作前的旧实例句柄,Intersect判定二者不属于同一个工作表实例,直接返回Nothing;逐行调试时每步操作都会触发VBA环境的消息循环,等待工作表实例刷新完成,所以不会触发问题。Wait语句是阻塞式等待,不会触发消息循环处理对象实例刷新,因此无法解决问题。
另外如果定义Range变量时没有显式绑定父工作表,用户窗体切换焦点时产生的隐式活动表变更,也会导致两个Range实际归属不同工作表,触发同样问题。

修复步骤

  1. 所有Range变量强制显式绑定父工作表:定义targetRow、rgRecName时,必须显式指定父对象为ThisWorkbook.Worksheets("Journal"),禁止省略父对象隐式调用活动表,从根源避免父表引用不一致。示例:
    Dim wsJournal As Worksheet
    Set wsJournal = ThisWorkbook.Worksheets("Journal")
    ' 定义范围时强制绑定wsJournal
    Set targetRow = wsJournal.Rows(Target.Row)
    Set rgRecName = wsJournal.Columns("B") ' 替换为实际的记录名列
    
  2. 保护状态切换后重新获取Range引用:不要在加/取消保护操作前定义Range然后跨操作使用,在调用PrUpr.UJournal完成取消保护后,重新执行一次targetRow、rgRecName的赋值操作,拿到刷新后的新实例句柄再执行Intersect。
  3. Intersect返回值强制校验:禁止直接对Intersect返回结果赋值,先判断返回值是否为Nothing再操作,避免错误91:
    Dim writeRng As Range
    Set writeRng = Intersect(targetRow, rgRecName)
    If Not writeRng Is Nothing Then
        writeRng.Value = foundName
    End If
    
  4. 补全UserInterfaceOnly参数初始化:UserInterfaceOnly:=True参数仅在单次设置保护的会话周期内生效,工作簿关闭重开后会自动重置为False,需要把PrUpr.PJournal的调用放到Workbook_Open事件中,每次打开工作簿自动重新设置保护,避免参数失效带来的异常。

内容的提问来源于stack exchange,提问作者Arno Z

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.26 13:54:21