개체가 VBA에서 컬렉션의 구성원인지 확인
개체가 VBA에서 컬렉션의 구성원인지 여부를 어떻게 확인합니까?
특히, 테이블 정의가 TableDefs
컬렉션 의 멤버인지 확인해야합니다 .
가장 좋은 방법은 컬렉션 구성원을 반복하고 찾고있는 것과 일치하는 것이 있는지 확인하는 것입니다. 저를 믿으십시오.
두 번째 해결책 (훨씬 더 나쁘다)은 "Item not in collection"오류를 포착 한 다음 항목이 존재하지 않는다는 플래그를 설정하는 것입니다.
충분하지 않나요?
Public Function Contains(col As Collection, key As Variant) As Boolean
Dim obj As Variant
On Error GoTo err
Contains = True
obj = col(key)
Exit Function
err:
Contains = False
End Function
정확히 우아하지는 않지만 내가 찾을 수있는 가장 좋은 (그리고 가장 빠른) 솔루션은 OnError를 사용하는 것입니다. 이는 중대형 컬렉션의 반복보다 훨씬 빠릅니다.
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
이것은 오래된 질문입니다. 모든 답변과 의견을주의 깊게 검토하고 성능에 대한 솔루션을 테스트했습니다.
컬렉션에 기본 요소와 개체가있을 때 실패하지 않는 내 환경에 가장 빠른 옵션을 생각해 냈습니다.
Public Function ExistsInCollection(col As Collection, key As Variant) As Boolean
On Error GoTo err
ExistsInCollection = True
IsObject(col.item(key))
Exit Function
err:
ExistsInCollection = False
End Function
또한이 솔루션은 하드 코딩 된 오류 값에 의존하지 않습니다. 따라서 매개 변수 col As Collection
는 다른 컬렉션 유형 변수로 대체 될 수 있으며 함수는 계속 작동해야합니다. 예를 들어 현재 프로젝트에서 col As ListColumns
.
컬렉션을 반복하기 위해 Microsoft 솔루션과 혼합 된 위의 제안에서이 솔루션을 만들었습니다.
Public Function InCollection(col As Collection, Optional vItem, Optional vKey) As Boolean
On Error Resume Next
Dim vColItem As Variant
InCollection = False
If Not IsMissing(vKey) Then
col.item vKey
'5 if not in collection, it is 91 if no collection exists
If Err.Number <> 5 And Err.Number <> 91 Then
InCollection = True
End If
ElseIf Not IsMissing(vItem) Then
For Each vColItem In col
If vColItem = vItem Then
InCollection = True
GoTo Exit_Proc
End If
Next vColItem
End If
Exit_Proc:
Exit Function
Err_Handle:
Resume Exit_Proc
End Function
이에 대해 제안 된 코드를 단축하고 예상치 못한 오류를 일반화 할 수 있습니다. 여기 있습니다 :
Public Function InCollection(col As Collection, key As String) As Boolean
On Error GoTo incol
col.Item key
incol:
InCollection = (Err.Number = 0)
End Function
특정 경우 (TableDefs) 컬렉션을 반복하고 이름을 확인하는 것이 좋은 방법입니다. 컬렉션 (Name)의 키가 컬렉션에있는 클래스의 속성이므로 괜찮습니다.
그러나 VBA 컬렉션의 일반적인 경우에는 키가 컬렉션의 개체의 일부일 필요는 없습니다 (예 : 컬렉션의 개체와 관련이없는 키를 사용하여 컬렉션을 사전으로 사용할 수 있음). 이 경우 항목에 액세스하고 오류를 포착 할 수밖에 없습니다.
컬렉션에 가장 적합한 편집 기능이 있습니다.
Public Function Contains(col As collection, key As Variant) As Boolean
Dim obj As Object
On Error GoTo err
Contains = True
Set obj = col.Item(key)
Exit Function
err:
Contains = False
End Function
이 버전은 기본 유형 및 클래스에 대해 작동합니다 (짧은 테스트 방법 포함).
' TODO: change this to the name of your module
Private Const sMODULE As String = "MVbaUtils"
Public Function ExistsInCollection(oCollection As Collection, sKey As String) As Boolean
Const scSOURCE As String = "ExistsInCollection"
Dim lErrNumber As Long
Dim sErrDescription As String
lErrNumber = 0
sErrDescription = "unknown error occurred"
Err.Clear
On Error Resume Next
' note: just access the item - no need to assign it to a dummy value
' and this would not be so easy, because we would need different
' code depending on the type of object
' e.g.
' Dim vItem as Variant
' If VarType(oCollection.Item(sKey)) = vbObject Then
' Set vItem = oCollection.Item(sKey)
' Else
' vItem = oCollection.Item(sKey)
' End If
oCollection.Item sKey
lErrNumber = CLng(Err.Number)
sErrDescription = Err.Description
On Error GoTo 0
If lErrNumber = 5 Then ' 5 = not in collection
ExistsInCollection = False
ElseIf (lErrNumber = 0) Then
ExistsInCollection = True
Else
' Re-raise error
Err.Raise lErrNumber, mscMODULE & ":" & scSOURCE, sErrDescription
End If
End Function
Private Sub Test_ExistsInCollection()
Dim asTest As New Collection
Debug.Assert Not ExistsInCollection(asTest, "")
Debug.Assert Not ExistsInCollection(asTest, "xx")
asTest.Add "item1", "key1"
asTest.Add "item2", "key2"
asTest.Add New Collection, "key3"
asTest.Add Nothing, "key4"
Debug.Assert ExistsInCollection(asTest, "key1")
Debug.Assert ExistsInCollection(asTest, "key2")
Debug.Assert ExistsInCollection(asTest, "key3")
Debug.Assert ExistsInCollection(asTest, "key4")
Debug.Assert Not ExistsInCollection(asTest, "abcx")
Debug.Print "ExistsInCollection is okay"
End Sub
컬렉션의 항목이 개체가 아닌 배열 인 경우 추가 조정이 필요합니다. 그 외에는 잘 작동했습니다.
Public Function CheckExists(vntIndexKey As Variant) As Boolean
On Error Resume Next
Dim cObj As Object
' just get the object
Set cObj = mCol(vntIndexKey)
' here's the key! Trap the Error Code
' when the error code is 5 then the Object is Not Exists
CheckExists = (Err <> 5)
' just to clear the error
If Err <> 0 Then Call Err.Clear
Set cObj = Nothing
End Function
출처 : http://coderstalk.blogspot.com/2007/09/visual-basic-programming-how-to-check.html
열쇠를 회수에 사용하지 않은 경우 :
Public Function Contains(col As Collection, thisItem As Variant) As Boolean
Dim item As Variant
Contains = False
For Each item In col
If item = thisItem Then
Contains = True
Exit Function
End If
Next
End Function
내 코드는 아니지만 꽤 잘 작성되었다고 생각합니다. 키뿐만 아니라 Object 요소 자체로 확인할 수 있으며 On Error 메서드와 모든 Collection 요소를 반복하는 작업을 모두 처리합니다.
https://danwagner.co/how-to-check-if-a-collection-contains-an-object/
링크 된 페이지에서 사용할 수 있으므로 전체 설명을 복사하지 않겠습니다. 나중에 페이지를 사용할 수 없게되는 경우 솔루션 자체가 복사됩니다.
코드에 대한 의심은 첫 번째 If 블록에서 GoTo가 과도하게 사용된다는 것입니다.하지만 누구나 쉽게 고칠 수 있으므로 원래 코드를 그대로 둡니다.
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
'INPUT : Kollection, the collection we would like to examine
' : (Optional) Key, the Key we want to find in the collection
' : (Optional) Item, the Item we want to find in the collection
'OUTPUT : True if Key or Item is found, False if not
'SPECIAL CASE: If both Key and Item are missing, return False
Option Explicit
Public Function CollectionContains(Kollection As Collection, Optional Key As Variant, Optional Item As Variant) As Boolean
Dim strKey As String
Dim var As Variant
'First, investigate assuming a Key was provided
If Not IsMissing(Key) Then
strKey = CStr(Key)
'Handling errors is the strategy here
On Error Resume Next
CollectionContains = True
var = Kollection(strKey) '<~ this is where our (potential) error will occur
If Err.Number = 91 Then GoTo CheckForObject
If Err.Number = 5 Then GoTo NotFound
On Error GoTo 0
Exit Function
CheckForObject:
If IsObject(Kollection(strKey)) Then
CollectionContains = True
On Error GoTo 0
Exit Function
End If
NotFound:
CollectionContains = False
On Error GoTo 0
Exit Function
'If the Item was provided but the Key was not, then...
ElseIf Not IsMissing(Item) Then
CollectionContains = False '<~ assume that we will not find the item
'We have to loop through the collection and check each item against the passed-in Item
For Each var In Kollection
If var = Item Then
CollectionContains = True
Exit Function
End If
Next var
'Otherwise, no Key OR Item was provided, so we default to False
Else
CollectionContains = False
End If
End Function
나는 Vadims 코드의 변형 인 이렇게했지만 좀 더 읽기 쉽습니다.
' Returns TRUE if item is already contained in collection, otherwise FALSE
Public Function Contains(col As Collection, item As String) As Boolean
Dim i As Integer
For i = 1 To col.Count
If col.item(i) = item Then
Contains = True
Exit Function
End If
Next i
Contains = False
End Function
I wrote this code. I guess it can help someone...
Public Function VerifyCollection()
For i = 1 To 10 Step 1
MyKey = "A"
On Error GoTo KillError:
Dispersao.Add 1, MyKey
GoTo KeepInForLoop
KillError: 'If My collection already has the key A Then...
count = Dispersao(MyKey)
Dispersao.Remove (MyKey)
Dispersao.Add count + 1, MyKey 'Increase the amount in relationship with my Key
count = Dispersao(MyKey) 'count = new amount
On Error GoTo -1
KeepInForLoop:
Next
End Function
'development' 카테고리의 다른 글
Swift 3 UnsafePointer ($ 0)는 더 이상 Xcode 8 베타 6에서 컴파일되지 않습니다. (0) | 2020.12.03 |
---|---|
Visual Studio Build Framework에서 .NET Core 2.2를 선택할 수 없음 (0) | 2020.12.03 |
Scala에서 빈 배열에 대한 정식 방법? (0) | 2020.12.03 |
PHP : 배열 키 대소 문자를 구분하지 않음 * 조회? (0) | 2020.12.03 |
Parcelable 인터페이스를 사용할 때 null 값을 직렬화하는 방법 (0) | 2020.12.03 |