2016-06-24 5 views
3

내 코드에 다른 컬렉션이 있습니다. 어떤 것은 (다양한 종류의) 객체를 보유하고, 다른 객체는 그 안에 Long과 같은 유형을 가지고 있습니다.Excel에서 컬렉션에 키가 있는지 확인하는 일반적인 방법

개체 및 개체에 대해 작동하는 컬렉션에 키가 포함되어 있는지 확인하는 방법이 있습니까?

지금까지 두 가지 기능이 있습니다.

첫 번째 기능 :

Private Function ContainsObject(objCollection As Object, strName As String) As Boolean 
    Dim o As Object 
    On Error Resume Next 
    Set o = objCollection(strName) 
    ContainsObject = (Err.Number = 0) 
    Err.Clear 
End Function 

두 번째 기능 :

Private Function ContainsLong(AllItems As Collection, TheKey As String) As Boolean 
    Dim TheValue As Long 
    On Error Resume Next 
    TheValue = AllItems.Item(TheKey) 
    ContainsLong = (Err.Number = 0) 
    Err.Clear 
End Function 

두 함수에 대한 이유는 ContainsObject 내가 걷고 쌍을 가지고있는 컬렉션을 전달하면 작동하지 않는다는 것입니다 (기능 항상 거짓을 반환합니다.

PS : 첫 번째 함수는 Test or check if sheet exists

에서 세 번째 대답의 사본입니다.
+0

오타가있는 것 같습니다. 마찬가지로'ContainsObject = (Err.Number = 0)'이어야한다. 비슷하게'CheckForKeyInCollection = (Err.Number = 0)'은'ContainsLong = (Err.Number = 0) ' – skkakkar

+0

편집 해 주셔서 감사합니다! 신속하게 문제를 설명하고 수정하는 답변을 수락했습니다. 다른 답변도 주셔서 감사합니다. 해결책도 거기에 있습니다.하지만 좀 더 미묘합니다 ... – user2606240

답변

9

첫 번째 기능에서는 Variant을 사용해야합니다. VariantObject을 지정할 수 있습니다. 이 오류되지 않습니다

Sub Test() 
    Dim var As Variant 
    Dim obj As Object 
    Set obj = Application 
    var = Application 
    Debug.Print var 
End Sub 

하지만이 할당하려고 즉 Type Mismatch 컴파일 오류를 줄 것이다 LongObject에 :

Sub Test() 
    Dim obj As Object 
    Dim lng As Long 
    lng = 3 
    Set obj = lng 
End Sub 

그래서, 일반적인 기능 (의 라인을 따라 당신의 Collection 키가 유효한지 확인하는 코드), 당신은 사용할 수 있습니다

Function HasKey(coll As Collection, strKey As String) As Boolean 
    Dim var As Variant 
    On Error Resume Next 
    var = coll(strKey) 
    HasKey = (Err.Number = 0) 
    Err.Clear 
End Function 

테스트 코드를 :

Sub Test() 
    Dim coll1 As New Collection 
    coll1.Add Item:=Sheet1.Range("A1"), Key:="1" 
    coll1.Add Item:=Sheet1.Range("A2"), Key:="2" 
    Debug.Print HasKey(coll1, "1") 

    Dim coll2 As New Collection 
    coll2.Add Item:=1, Key:="1" 
    coll2.Add Item:=2, Key:="2" 
    Debug.Print HasKey(coll2, "1") 
End Sub 

유용한 정보가 MSDN에 있습니다. 컨텍스트는 VB6이지만 VBA와 관련이 있습니다.

+0

사실과 현재의 답변에 대한 감사의 말씀을 전합니다. – skkakkar

+0

@skkakkar - 귀하의 답변은 내가 선호하는 '사전'객체를 사용하는 것이 좋습니다. OP는'Collection' 객체를 사용하고 있으며'Dictionary'로 전환 할 기회가 없을 수도 있습니다. 말처럼 중간 말을 바꾸는 것이 항상 가능하지는 않습니다 :) –

2

게시물 수정 중에 댓글 당 몇 자루의 오류가 이미 수정되었습니다. 귀하의 질문에 대한 답변으로 관련 측면을 다루고 싶습니다.
컬렉션에 키를 사용하는 동안은 주로 세 가지 장점
- 순서는 여전히 올바른 항목에 액세스 코드를 변경하는 경우 - 당신은 직접 전체 컬렉션을 읽지 않고 항목에 액세스 할 수 있습니다 것은
- 그것은 당신에게 할 수 있습니다 더 읽기 쉬운 코드.

* 그러나 동시에 컬렉션

  • 에 키를 이용하여 주로 세 가지 문제는 키가

  • 존재하는 경우 당신은 키

  • 을 변경할 수 없습니다 확인할 수있다
  • 키를 검색 할 수 없습니다.

Pearsons 기사에 따르면 컬렉션의 키는 쓰기 전용이므로 컬렉션의 기존 키 목록을 가져올 방법이 없습니다. 또한 인용 된 단락을 겪고 : -

Here, Coll is a Collection object in which we will store multiple CFile objects. The CollKeys Collection is used to store the keys of the CFile objects stored in the Coll Collection. We need this second Collection because the Keys of a Collection are write-only -- there is no way to get a list of existing Keys of a Collection. One of the enhancements provided by CFiles is the ability to retrieve a list of Keys for the Collection.

Custom Collection Classes

한 가지 방법이 일치 당신이 찾고있는 무엇을하고 다른 방법으로는 잡을 경우 컬렉션의 멤버를 통해 반복하고 보는 것입니다 Item not in collection 오류가 표시되고 해당 항목이 존재하지 않는다고 알리는 플래그를 설정하십시오. 이러한 접근 방식에 대한 의견 차이는 있지만 어떤 사람들은 오류를 포착하는 좋은 방법이 아니라고 느낀 반면 다른 섹션에서는 어떤 중간 규모 이상의 대규모 컬렉션에 대한 반복보다 훨씬 빠르다고 느낍니다.
오류를 잡는 방법을 찾으면 오류 번호는 오류의 원인에 따라 다릅니다. 오류를 확인하려면 코드 루틴이 필요합니다. 가장 간단한 방법 일 수 있습니다. 다양한 전문가들에 의해 제안 된

'c1 is the collection 
For i = 1 To c1.Count 
    Debug.Print Err.Number, Err.Description 
    If Err.Number <> 0 Then Err.Clear 
Next i 

오류 잡기 루틴들이 중요하다고 생각하고 자신의 routine.Various 일반적으로 컬렉션 개체와 관련된 오류 번호를 발생에 포함 오류 번호에 차이가 있습니다 : -

  • Error 5 잘못된 프로 시저 호출 또는 현재 플랫폼에서 유효하지 않은 프로 시저를 호출하려고 시도하면이 오류가 발생할 수도 있습니다. 예를 들어, 일부 절차는 Microsoft Windows 또는 Macintosh 용으로 만 유효합니다.
  • error 438 "객체는 객체 클래스의 인스턴스 인이 속성 또는 메서드를 지원하지 않습니다. 클래스의 인스턴스가 그 클래스 유형 정의에 정의 된 일부 속성 을 지원하며,이 중 하나를 지원하지 않습니다.
  • Error 457이 키는 이미 이미 컬렉션의 다른 부재를 식별하는 회수 부재의 핵심이 collection.You의 요소를 지정된 연관된.이 부재하는 다른 키 선택.
  • Error 91 Object 변수 또는 블록 변수하지 set.There 만들려면 두 개의 단계가 있습니다. 객체 변수. 먼저 개체 변수를 선언해야합니다. 그런 다음 Set 문을 사용하여 객체 변수에 유효한 참조를 할당해야합니다. 유효한 개체를 아직 참조하지 않고있는 개체 변수를 사용하려고했습니다.
  • Error 450 잘못된 인수 또는 잘못된 속성 지정.읽기 전용 속성에 값을 할당하려고 procedure.If 절차 에 대한 호출에서 인수의 수는 중

의 예상 필요한 인수의 수와 동일하지 않았다 위의 오류 오류 번호 438은 중요하고 다른 하나는 5로 간주되었습니다. 나는 Mark Nold가 2008 년 7 년 전 게시 한 샘플 테스트 프로그램에 함수 루틴을 포함시키고 있으므로 그에 대한 신용으로 SO 질문 Determining whether an object is a member of a collection in VBA을 게시합니다.

오류 457과 같은 일부 오류는 프로그램 테스트 실행시 허용되지 않습니다. 중복 키 데이터로 채워 넣으려고했으나 스냅 샷과 같이 프로그램 자체 테스트시 오류가 발생했습니다. error 457

사진을 제거한 후 스냅 샷과 같이 올바른 출력이 표시됩니다.

no error

는 독립적 배열의 키 값을 저장하지 않고 바닐라 컬렉션 모음의 키의리스트를 얻을 수없는 경우가 있습니다. 이 작업을 수행하는 가장 쉬운 방법은 Microsoft Scripting Runtime &에 대한 참조를 추가하는 것입니다. 내 프로그램의 키 목록을 얻으려면이 방법을 포함 시켰습니다.
Collection을 채우는 동안 키가 두 번째 매개 변수이고 고유 한 문자열이어야합니다.

내 프로그램의 전체 코드는입니다.

Sub Generic_key_check() 
    Dim arr As Variant 
    Dim c1 As New Collection 
    Dim dic As Object 
    With Application 
    .ScreenUpdating = False 
    End With 


    Set dic = CreateObject("Scripting.Dictionary") 
    dic.CompareMode = vbTextCompare 

    'Populate the collection 
    c1.Add "sheet1", "sheet1" 
    c1.Add "sheet2", "sheet2" 
    c1.Add "sheet3", "sheet3" 
    c1.Add "sheet4", "sheet4" 
    c1.Add "sheet5", "sheet5" 
    c1.Add 2014001, "Long1" 
    c1.Add 2015001, "Long2" 
    c1.Add 2016001, "Long3" 
    c1.Add 2015002, "Long4" 
    c1.Add 2016002, "Long5" 

    'Populate the dictionary 
    dic.Add "sheet1", "sheet1" 
    dic.Add "sheet2", "sheet2" 
    dic.Add "sheet3", "sheet3" 
    dic.Add "sheet4", "sheet4" 
    dic.Add "sheet5", "sheet5" 
    dic.Add "Long1", 2014001 
    dic.Add "Long2", 2015001 
    dic.Add "Long3", 2016001 
    dic.Add "Long4", 2015002 
    dic.Add "Long5", 2016002 
    ' Get a list of key items by Dictionary Method 
    Dim N As Variant 
    For Each N In dic.Keys 
    Debug.Print "Key: " & N, "Value: " & dic.item(N) 
    Next 
    'Test for two types of data whether key exists or not. 
    If InCollection(c1, "Long1") Then 
    'If Exists("Long1", c1) Then 
    Debug.Print "Good" 

    Else 
    ' If there is error then print out the error number and its description. 
    Debug.Print Err.Number, Err.Description 
    Debug.Print "Not Good" 
    End If 
    If InCollection(c1, "sheet2") Then 
    Debug.Print "Good" 

    Else 
    Debug.Print Err.Number, Err.Description 
    Debug.Print "Not Good" 
    End If 

    'Checking whether desired key has populated correctly 
    Debug.Print c1("Sheet1") 
    Debug.Print c1("Long3") 



    'Listing out collection items to check theyexist in the collection. 
    For i = 1 To c1.Count 
    Debug.Print c1.item(i) 
    Next i 
    With Application 
    .ScreenUpdating = True 
    End With 
    Set c1 = Nothing 
End Sub 
Public Function InCollection(col As Collection, key As String) As Boolean 
    Dim var As Variant 
    Dim errNumber As Long 

    InCollection = False 
    Set var = Nothing 

    Err.Clear 
    On Error Resume Next 
    var = col.item(key) 
    errNumber = CLng(Err.Number) 
    On Error GoTo 0 

    '5 is not in, 0 and 438 represent incollection 
    If errNumber = 5 Then ' it is 5 if not in collection 
    InCollection = False 
    Else 
    InCollection = True 
    End If 

End Function 

직접 실행 창에 표시된 프로그램 당 최종 출력이 스냅 샷에 표시됩니다.
enter image description here

+0

Scripting Runtime 라이브러리에서'Dictionary'의 응용 프로그램을 보여주는 +1. Excel VBA의 기본 부분이 아니라는 것은 부끄러운 일입니다. –

관련 문제