Excel VBA의 컬렉션에 키가 있는지 확인하는 일반적인 방법
코드에 다른 컬렉션이 있습니다.개체(다양한 종류)를 포함하는 개체도 있고, 유형(예: 길이)을 포함하는 개체도 있습니다.
개체뿐만 아니라 유형에도 사용할 수 있는 키가 컬렉션에 포함되어 있는지 확인할 수 있는 방법이 있습니까?
지금까지 저는 두 가지 기능이 있습니다.
첫 번째 기능:
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
두 함수의 이유는 Longs 쌍이 있는 Collection을 전달하면 ContainsObject가 작동하지 않는 것 같기 때문입니다(함수는 항상 False를 반환합니다).
추신: 첫 번째 기능은 테스트 또는 시트가 존재하는지 확인하는 세 번째 답변의 사본입니다.
다음을 사용해야 합니다.Variant
제1기능으로할당할 수 있습니다.Object
Variant
예: 오류가 발생하지 않습니다.
Sub Test()
Dim var As Variant
Dim obj As Object
Set obj = Application
var = Application
Debug.Print var
End Sub
하지만 이것이 줄 것입니다.Type Mismatch
컴일오, 즉할시를 하려고 시도하는 Long
완전히Object
:
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와 관련이 있습니다.
게시물을 편집하는 동안 이미 수정된 주석에 따른 오타는 거의 없습니다.당신의 질문에 대해 저는 관련된 부분을 다루고 싶습니다.
하는 것은 세 가지 .
항목에 . - 않고 수 . 전체 컬렉션을 읽지 않고 항목에 직접 액세스할 수 있습니다.
코드를 더 읽기 쉽게 만들 수 있습니다.
*그러나 동시에 컬렉션에서 키를 사용할 때 주로 세 가지 문제가 있습니다.
키가 있는지 확인할 수 없습니다.
키를 변경할 수 없습니다.
키를 검색할 수 없습니다.
Pearson 문서에 따르면 컬렉션의 키는 쓰기 전용입니다. 기존 컬렉션의 키 목록을 가져올 수 없습니다.인용된 단락 추가 설명:-
여기서 Coll은 여러 CFile 개체를 저장할 Collection 개체입니다.CollKeys Collection은 Collection에 저장된 CFile 개체의 키를 저장하는 데 사용됩니다.컬렉션의 키가 쓰기 전용이기 때문에 두 번째 컬렉션이 필요합니다. 기존 컬렉션의 키 목록을 가져올 수 없습니다.CFiles에서 제공하는 향상된 기능 중 하나는 수집용 키 목록을 검색하는 기능입니다.
한 가지 방법은 컬렉션의 구성원에게 반복하여 찾고 있는 것과 일치하는지 확인하는 것이고 다른 방법은 다음과 같습니다.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
다양한 전문가가 제안하는 오류 감지 루틴은 중요하다고 생각하고 루틴에 포함되는 오류 수가 다릅니다.수집 개체와 관련하여 일반적으로 발생하는 다양한 오류 번호는 다음과 같습니다.
Error 5
잘못된 프로시저 호출 또는 인수입니다.현재 플랫폼에서 유효하지 않은 프로시저를 호출하려는 경우에도 이 오류가 발생할 수 있습니다.예를 들어 일부 절차는 마이크로소프트 윈도우즈 또는 Macintosh 등에서만 유효할 수 있습니다.error 438
"개체가 이 속성 또는 메서드를 지원하지 않습니다. 개체가 클래스 인스턴스입니다.클래스 인스턴스는 해당 클래스 유형 정의에 정의된 일부 속성을 지원하며 이 속성은 지원하지 않습니다.Error 457
이 키는 이미 이 컬렉션의 요소와 연결되어 있습니다.컬렉션의 다른 멤버를 이미 식별하는 컬렉션 멤버에 대한 키를 지정했습니다.이 구성원에 대해 다른 키를 선택하십시오.Error 91
개체 변수 또는 블록 변수가 설정되지 않았습니다.개체 변수를 만드는 데는 두 가지 단계가 있습니다.먼저 개체 변수를 선언해야 합니다.그런 다음 Set 문을 사용하여 개체 변수에 유효한 참조를 할당해야 합니다.아직 유효한 개체를 참조하지 않는 개체 변수를 사용하려고 했습니다.Error 450
인수 수가 잘못되었거나 속성 할당이 잘못되었습니다.프로시저 호출의 인수 수가 프로시저에서 예상하는 필수 인수 수와 다릅니다., 다음과 같습니다.
위의 오류 중 438번의 오류가 중요한 것으로 간주되었고, 나머지 하나는 5번입니다.7년 전 마크 놀드가 2008년 비디오 SO 질문에 올린 샘플 테스트 프로그램에 함수 루틴을 통합하고 있습니다. 개체가 VBA에서 컬렉션의 구성원인지 여부를 결정하는 것은 그에게 합당한 크레딧입니다.
오류 457과 같은 일부 오류는 프로그램 테스트 실행 시 허용되지 않습니다.중복된 키 데이터를 입력하려고 했는데, 스냅샷과 같이 프로그램 테스트 시 오류가 발생했습니다.
제거 후 스냅샷에 표시된 것처럼 정확한 출력이 표시됩니다.
개별 배열에 키 값을 저장하지 않고 바닐라 컬렉션을 포함한 컬렉션의 키 목록을 가져올 수 없습니다.이렇게 하는 가장 쉬운 방법은 Microsoft 스크립팅 런타임에 참조를 추가하고 대신 보다 기능이 뛰어난 사전을 사용하는 것입니다.프로그램에 키 목록을 가져오기 위해 이 접근 방식을 포함했습니다.
수집을 채우는 동안 키가 두 번째 매개 변수이며 고유한 문자열이어야 합니다.
제 프로그램의 전체 코드는.
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
즉시 창에 표시된 프로그램에 따른 최종 출력이 스냅샷에 표시되었습니다.
사도는 그들의 대답이 거의 정확합니다.Robin의 응답은 일반 객체에서는 작동하지 않지만 Excel의 Range 객체에서는 셀의 값을 반환하기 때문에 기록된 대로 작동합니다.저는 사도가 IsObject를 사용하는 것을 좋아합니다(대부분 이것도 제가 알아낸 것이기 때문입니다).하지만 코드는 약간 너무 복잡합니다.
IsObject 컬렉션에 키가 있으면 변형이 True 또는 False로 설정되고, 그렇지 않으면 변형이 비어 있으면 오류가 무시됩니다.
Function HasKey(col As Collection, Key As String) As Boolean
Dim v As Variant
On Error Resume Next
v = IsObject(col.Item(Key))
HasKey = Not IsEmpty(v)
End Function
만약 당신이 PaulE의 기능을 조금 더 유연하게 만들고 싶다면, 문자열 매개변수를 Variant로 변경할 수 있다는 것을 지적하고 싶습니다. 즉, 이제 그것을 사용하여 항목 키나 항목 번호를 확인할 수 있습니다. 이것은 편리합니다.많은 컬렉션을 확인하려는 경우 변형은 약간 느리지만 대부분의 경우 두 기능이 유사하게 작동합니다.
Function HasItem(col As Collection, ItemKeyOrNum As Variant) As Boolean
Dim v As Variant
On Error Resume Next
v = IsObject(col.Item(ItemKeyOrNum))
HasItem = Not IsEmpty(v)
End Function
여기서 허용된 답은 틀렸습니다(이것은 제가 알아차린 다른 많은 질문에도 해당되므로 주의하고 모든 답을 읽으십시오).사도와 바울은 거기서 질문받은 특정한 질문에 대한 가장 정확한 대답을 위해 협력했습니다.저는 수락된 답변을 사용하려고 했지만, 작동하지 않았습니다.
질문에는 "객체뿐만 아니라 유형에도 사용할 수 있는 키가 컬렉션에 포함되어 있는지 확인할 수 있는 방법이 있습니까?"라고 명시되어 있습니다.
승인된 답변은 개체에 적용되지 않습니다.폴 E의 대답은 최종 정답입니다.저는 기능을 좀 더 만능으로 만들기 위해 여기에 약간의 뉘앙스를 덧붙이고 있습니다.
한 문자열의 짧은 변형:
Function keyExists(coll As Collection, key As String) As Boolean
On Error Resume Next: keyExists = IsObject(coll(key)) Or True
End Function
먼저 keyExists = false입니다.오류를 무시하도록 설정된 오류 트랩입니다.식(항상 TRUE)이 오류 없이 계산된 경우(키가 있는 요소가 있음), keyExists는 TRUE였습니다.
다양한 유형의 값을 수집하여 사용하는 경우:
Sub testExist()
Dim coll As New Collection
coll.Add New Collection, "1"
coll.Add Array(1, 1), "3"
coll.Add 1, "5"
coll.Add "1111", "9"
For i = 1 To 10
Debug.Print "key " & i & " is " & IIf(keyExists(coll, CStr(i)), "Exists", "Absent")
Next
End Sub
집합을 사용하여 할당해야 하고 그렇지 않으면 메서드가 False를 반환하는 오류를 생성해야 하기 때문에 컬렉션에 기본 유형이 아닌 개체가 포함된 경우 Robin의 메서드가 실패합니다.다음은 약간의 조정입니다.
'Test if a key is available in a collection
Public Function HasKey(coll As Collection, strKey As String) As Boolean
On Error GoTo IsMissingError
Dim val As Variant
' val = coll(strKey)
HasKey = IsObject(coll(strKey))
HasKey = True
On Error GoTo 0
Exit Function
IsMissingError:
HasKey = False
On Error GoTo 0
End Function
언급URL : https://stackoverflow.com/questions/38007844/generic-way-to-check-if-a-key-is-in-a-collection-in-excel-vba
'programing' 카테고리의 다른 글
판다 .iloc에게 단일 행 데이터 프레임을 반환하도록 강요하는 것? (0) | 2023.08.14 |
---|---|
"지정된 키 'utf8mb4'가 사전에 없습니다. (0) | 2023.08.14 |
핀치를 감지하는 가장 간단한 방법 (0) | 2023.08.14 |
요청 간의 차이점은 무엇입니까?사용자 호스트 주소 및 요청.서버 변수["REMOTE_ADDR"].문자열로() (0) | 2023.08.14 |
주어진 컨텍스트에서 레이아웃 인플레이터를 얻는 방법? (0) | 2023.08.14 |