【问题标题】:Excel VBA Error 1004 on range objects using range names scoped to the Workbook level范围对象上的 Excel VBA 错误 1004 使用范围为工作簿级别的范围名称
【发布时间】:2020-09-04 11:18:55
【问题描述】:

为什么这段代码停止工作了?

几十年,我在 VBA 中使用范围为工作簿级别的 Excel 范围名称,而在大多数情况下,不必使用它们的 Sheets() 对象父对象来限定 Range() 对象。最近,如果命名范围不在活动工作表上,这将停止工作,现在会引发 1004 错误。

曾经有效的代码

If Range("SNAP_Current").Value = Range("SNAP_Backup").Value Then
    debug.print "True"
else
    debug.print "False"
End If

在这种情况下,“SNAP_Current”在活动工作表上,“SNAP_Backup”不在活动工作表上。 当然,如果 Range() 使用正确的 Sheet() 对象进行限定,代码就可以工作。

If Range("SNAP_Current").Value = **Sheets("Backup Copy").**Range("SNAP_Backup").Value Then
    debug.print "True"
else
    debug.print "False"
End If

我明白为什么使用 sheet() 限定符可以使代码正常工作。例如,如果范围名称限定为工作表,则需要 Sheets() 限定符。但是,当 range_name 范围限定为工作簿级别时,我不想更改我的所有 VBA 代码(我有很多)以使用 Sheet() 对象限定 Range() 对象。我希望有一些我无意中更改的内容可以撤消以恢复功能。

谁能告诉我为什么以前的代码在没有 Sheet() 对象限定符的情况下也能正常工作? 我是否缺少图书馆,或者我是否有两个冲突的图书馆? 我怎样才能恢复这个功能?

顺便说一句,https://docs.microsoft.com/en-us/office/vba/excel/concepts/cells-and-ranges/refer-to-named-ranges 确认 Range() 应该适用于工作簿级别的命名范围。

【问题讨论】:

  • 根据我的经验,这里的大多数 VBA 人员会建议您使用 Workbook/Worksheet 完全限定任何 Range 调用。
  • Range() 适用于工作簿级别的命名范围,但适用于当前活动的工作簿。这是你的问题吗?我永远不会使用不合格的 Excel 对象(工作表、范围、单元格、形状...)
  • 我相信如果没有工作表限定符,excel 将尝试使用Activesheet 创建范围引用。正如您所提到的,这两个 NamedRanges 位于不同的工作表上,因此不能都在 activesheet 上。
  • 你能验证你的命名范围确实是工作簿级别的吗?是否已更改为工作表范围?
  • 无论活动工作表如何,我都可以访问工作簿范围内的命名范围。

标签: excel vba named-ranges


【解决方案1】:

如果在工作簿级别定义了命名范围,则无需使用工作表对其进行限定。如果您使用工作表对其进行限定,则它必须是范围指向的工作表。但是,如果您不限定它,Excel 将在 ActiveWorkbook 中查找范围,这不一定是您期望的工作簿。

我创建了一个包含 2 个工作表的工作簿,具有三个命名范围:
MyGlobalRange 是在 Workbook 级别声明的范围,指向工作表 1。
MyLocalRange1 是在 Worksheet 级别声明的 Range,指向工作表 1。
MyLocalRange2 是在 Worksheet 级别声明的 Range,指向工作表 2。

以下代码显示了在什么情况下可以访问哪个范围。首先,sheet1 处于活动状态,接下来是 sheet2,最后我创建了一个新的工作簿,它获取 活动工作簿

Sub testSub()
    ThisWorkbook.Activate
    ThisWorkbook.Sheets(1).Activate
    DumpNamedRanges "Sheet 1"
    ThisWorkbook.Sheets(2).Activate
    DumpNamedRanges "Sheet 2"
    Dim newWB As Workbook
    Set newWB = Workbooks.Add
    DumpNamedRanges "new Workbook"
    newWB.Close False
End Sub

Sub DumpNamedRanges(msg As String)
    On Error Resume Next
    Debug.Print msg, "G unqual :", Range("MyGlobalRange").Value
    Debug.Print msg, "G sheet 1:", ThisWorkbook.Sheets(1).Range("MyGlobalRange").Value
    Debug.Print msg, "G sheet 2:", ThisWorkbook.Sheets(2).Range("MyGlobalRange").Value
    Debug.Print msg, "L1 unqual:", Range("MyLocalRange1").Value
    Debug.Print msg, "L1 qual  :", ThisWorkbook.Sheets(1).Range("MyLocalRange1").Value
    Debug.Print msg, "L2 unqual:", Range("MyLocalRange2").Value
    Debug.Print msg, "L2 qual  :", ThisWorkbook.Sheets(2).Range("MyLocalRange2").Value
    On Error Goto 0
End Sub

这就是结果。 On Error Resume Next 会跳过不工作的行

Sheet 1       G unqual :    I am global
Sheet 1       G sheet 1:    I am global
Sheet 1       L1 unqual:    I am local sheet 1
Sheet 1       L1 qual  :    I am local sheet 1
Sheet 1       L2 qual  :    I am local sheet 2
Sheet 2       G unqual :    I am global
Sheet 2       G sheet 1:    I am global
Sheet 2       L1 qual  :    I am local sheet 1
Sheet 2       L2 unqual:    I am local sheet 2
Sheet 2       L2 qual  :    I am local sheet 2
new Workbook  G sheet 1:    I am global
new Workbook  L1 qual  :    I am local sheet 1
new Workbook  L2 qual  :    I am local sheet 2

只要工作簿处于活动状态,您就可以访问在不合格工作簿级别上声明的范围。合格后,必须使用正确的纸张。
当工作表本身处于活动状态时,可以不限定访问在工作表级别声明的范围。
但是当不同的工作簿被激活时,所有范围都只能访问限定。

不用说,解决方案不应该是使用Activate- 命令来解决该问题。始终满足所有条件,永远不要依赖 ActivesheetActiveWorkbook

【讨论】:

  • 感谢所有 cmets。是的,范围名称都限定在工作簿级别。我正在使用 w
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-01-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-11-04
相关资源
最近更新 更多