programing

VBA에 범위가 있는지 테스트합니다.

telecom 2023. 8. 13. 09:32
반응형

VBA에 범위가 있는지 테스트합니다.

이렇게 시작 날짜와 종료 날짜를 기준으로 테이블에서 데이터를 가져오는 동적으로 정의된 명명된 범위가 Excel에 있습니다.

=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

그러나 "Runtime error 1004, 객체 '_Global'의 메서드 'Range'가 실패했습니다."라는 메시지가 표시됩니다.

여기 명명된 범위가 존재하는지 여부를 반환하기 위해 생성한 함수가 있습니다.도움이 될 수도 있습니다.

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

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

이것은 또 다른 접근법입니다.테스트할 용기와 이름을 선택할 수 있는 장점이 있습니다.즉, 시트 이름이나 워크북 이름 등을 테스트할 수 있습니다.

다음과 같이:

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

수행 중인 응용 프로그램에 따라 사전 사용을 고려하는 것이 좋습니다.특히 무언가가 존재하는지 확인하고 싶을 때 유용합니다.다음 예를 들어 보겠습니다.

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 메서드를 사용하여 이 문제를 방지할 수 있습니다.사전 사용 방법에 대한 좋은 참조가 필요하면 이 사전을 사용하십시오.

행운을 빕니다.

이 게시물은 오래된 게시물이지만 평가된 답변 중 어떤 것도 테스트할 수 있는 동적 솔루션을 가지고 있지 않습니다.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가 동적으로 정의된 범위를 가지고 있기 때문에 이 특정 질문에는 효과가 없었을 것이라는 점에 주목할 필요가 있습니다.이 질문은 이름이 유효한 범위인지 테스트라는 더 정확한 제목을 붙였을 것입니다.name항상 공식으로 존재했습니다. 문제는 유효한 범위인지 여부였습니다.워크북과 시트를 모두 확인하는 솔루션으로 이 문제를 해결하려면...이 기능은 작동합니다.

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

언급URL : https://stackoverflow.com/questions/12611900/test-if-range-exists-in-vba

반응형