详细说明,假设我的工作簿中有两个命名范围。两个命名区域具有相同的名称(假设为"myName"),但一个范围的作用域为 Sheet1,另一个范围限定为工作簿。
给定命名范围的名称(字符串),我想获取工作簿级别的命名范围。
如果我使用本机调用:wb.Names.Item("myName")
,它将返回工作表范围的命名范围。
相反,如果我这样做:wb.Names.Item("Sheet1!myName")
,这显然返回工作表范围的名称范围。我发现我可以使用它来指定特定于工作表的,但不能指定工作簿。
无论如何,我可以指定我想要工作簿范围吗?
我的解决方法是当前遍历所有名称的列表,并比较.用于获取工作簿范围命名区域的 Name 属性。这是有效的,因为 .Name 属性将"Sheet1!"追加到工作表范围的命名区域。然而,这样做的成本非常高,我想避免它。
当我们(JKP 和我自己)编写名称管理器时,我们专门为重复的全局/本地名称添加了过滤器和警告消息,因为您提到的此 Excel 对象模型行为会导致难以检测的错误。
所以我的建议是永远不要使用重复的全局/本地名称。
我们使用代码来检测名称是否重复全局/本地,并且本地名称的父名称处于活动状态,然后在必要时切换工作表。我们用来查找全局名称的本地版本的优化 VBA 代码是这样的:除非您有数万个名称,否则它的速度相当快 -
Function FindNameLocal(oSheet As Worksheet, sName As String) As Name
Dim oName As Name
Dim strLocalName As String
Dim strLocalNameNoQuote
Dim strName As String
Set FindNameLocal = Nothing
If Len(sName) > 0 And Not oSheet Is Nothing And oSheet.Names.Count > 0 Then
On Error Resume Next
strLocalName = "'" & oSheet.Name & "'!" & sName
strLocalNameNoQuote = oSheet.Name & "!" & sName
Set FindNameLocal = oSheet.Names(strLocalName)
If Err <> 0 Or (FindNameLocal.NameLocal <> strLocalName And FindNameLocal.NameLocal <> strLocalNameNoQuote) Then
On Error GoTo 0
Set FindNameLocal = Nothing
For Each oName In oSheet.Names
strName = oName.Name
If Len(strLocalName) = Len(strName) Or Len(strLocalNameNoQuote) = Len(strName) Then
If strName = strLocalName Or strName = strLocalNameNoQuote Then
Set FindNameLocal = oName
GoTo GoExit
End If
End If
Next
End If
End If
GoExit:
End Function