12

我的 excel ss 中有一个动态定义的命名范围,它根据像这样的开始日期和结束日期从表中抓取数据

=OFFSET(Time!$A$1,IFERROR(MATCH(Date_Range_Start,AllDates,0)-1,MATCH(Date_Range_Start,AllDates)),1,MATCH(Date_Range_End,AllDates)-IFERROR(MATCH(Date_Range_Start,AllDates,0)-1,MATCH(Date_Range_Start,AllDates)),4)

但是,如果日期范围在表中没有数据,则该范围不存在(或某些东西,idk)。如何在 VBA 中编写代码来测试此范围是否存在?

我尝试过类似的东西

If Not Range("DateRangeData") Is Nothing Then

但我收到“运行时错误 1004,对象 '_Global' 的方法 'Range' 失败。”

4

5 回答 5

32

这是我敲出的一个函数,用于返回是否存在命名范围。它可能会帮助你。

Function RangeExists(R As String) As Boolean
    Dim Test As Range
    On Error Resume Next
    Set Test = ActiveSheet.Range(R)
    RangeExists = Err.Number = 0
End Function
于 2013-10-04T10:52:26.600 回答
17

您可以在 VBA 中复制匹配以在使用范围之前计算您将拥有多少行,或者您可以使用错误处理:

On Error Resume Next

Debug.Print range("DateRangeData").Rows.Count

If Err = 1004 Then
    MsgBox "Range Empty"
    Exit Sub
Else
    MsgBox "Range full"
End If

Err.Clear
On Error GoTo 0
于 2012-09-26T23:39:07.153 回答
3

这是另一种方法。它的优点是取容器和要测试的名称。这意味着您可以测试工作表名称或工作簿名称。

像这样:

If NamedRangeExists(ActiveSheet.Names, "Date") Then
    ...
Else
...
End If

或者

If NamedRangeExists(ActiveWorkbook.Names, "Date") Then
   ...
Else
   ...
End If

Public Function NamedRangeExists(ByRef Container As Object, item As String) As Boolean


Dim obj As Object
Dim value As Variant

On Error GoTo NamedRangeExistsError:

    value = Container(item)
    If Not InStr(1, CStr(value), "#REF!") > 0 Then
        NamedRangeExists = True
    End If
    Exit Function

Exit Function

NamedRangeExistsError:
    NamedRangeExists = False
End Function
于 2014-02-07T17:07:06.783 回答
1

根据您正在执行的应用程序,最好考虑使用字典。当您想检查某物是否存在时,它们特别有用。举个例子:

Dim dictNames as Scripting.Dictionary

Sub CheckRangeWithDictionary()

    Dim nm As Name

    'Initially, check whether names dictionary has already been created
    If Not dictNames Is Nothing Then
        'if so, dictNames is set to nothing
        Set dictNames = Nothing
    End If

    'Set to new dictionary and set compare mode to text
    Set dictNames = New Scripting.Dictionary
    dictNames.CompareMode = TextCompare

    'For each Named Range
    For Each nm In ThisWorkbook.Names
        'Check if it refers to an existing cell (bad references point to "#REF!" errors)
        If Not (Strings.Right(nm.RefersTo, 5) = "#REF!") Then
            'Only in that case, create a Dictionary entry
            'The key will be the name of the range and the item will be the address, worksheet included
            dictNames(nm.Name) = nm.RefersTo
        End If
    Next

    'You now have a dictionary of valid named ranges that can be checked

End Sub

在您的主要程序中,您需要做的就是在使用范围之前进行存在性检查

Sub CopyRange_MyRange()

    CheckRangeWithDictionary

    If dictNames.exists("MyRange") then
        Sheets(1).Range("MyRange").Copy
    end if

End Sub

虽然加载字典可能看起来有点长,但处理和搜索速度非常快。检查是否存在引用有效地址的任何命名范围也变得更加简单,而无需在这个简单的应用程序中使用错误处理程序。

请注意,在工作表级别而不是工作簿级别使用名称时,有必要使用更精细的键来保证唯一性。从创建字典的方式来看,如果重复某个键,则会覆盖项目值。这可以通过使用与密钥创建语句中的检查相同的Exists方法来避免。如果您需要有关如何使用字典的良好参考,请使用这个

祝你好运!

于 2017-02-22T04:32:01.710 回答
0

这是一篇旧帖子,但没有一个评分答案具有动态解决方案来测试name工作簿或工作表中是否存在。下面的这个函数将完成:

Function pg_Any_Name(thename As String) As Boolean
Dim n As Name, t As String
   
   For Each n In ThisWorkbook.Names
      t = Mid(n.Name, InStr(1, n.Name, "!", vbTextCompare) + 1, 999)

      If UCase(thename) = UCase(t) Then
         pg_Any_Name = True
         Exit Function
      End If
   Next n

End Function

值得注意的是,这不适用于这个特定问题,因为 OP 有一个动态定义的范围。这个问题应该更准确地命名为Test if Name is a Valid Range因为name总是作为公式存在,问题是它是否是有效的RANGE。要使用同时检查工作簿和工作表的解决方案来解决此问题...此功能将起作用:

Function PG_Range_Name(thename As String) As Boolean
Dim n As Name, t As String
  
   For Each n In ThisWorkbook.Names
      t = Mid(n.Name, InStr(1, n.Name, "!", vbTextCompare) + 1, 999)
      
      If UCase(thename) = UCase(t) Then
         On Error Resume Next
         PG_Range_Name = n.RefersToRange.Columns.Count > 0
         Exit Function
      End If
   Next n

End Function
于 2021-11-30T02:07:49.403 回答