我在目前的工作场所继承了一个大型VB6应用程序。我在工作中学习VB6,我遇到了很多问题。目前的主要问题是我无法弄清楚如何检查Collection对象中是否存在密钥。有人可以帮忙吗?
答案 0 :(得分:26)
我的标准功能非常简单。无论元素类型如何,这都可以工作,因为它不需要做任何赋值,它只执行集合属性get。
Public Function Exists(ByVal oCol As Collection, ByVal vKey As Variant) As Boolean
On Error Resume Next
oCol.Item vKey
Exists = (Err.Number = 0)
Err.Clear
End Function
答案 1 :(得分:21)
@Mark Biek您的keyExists与我的标准Exists()函数非常匹配。为了使类对COM公开的集合更有用并检查数字索引,我建议将sKey和myCollection更改为不键入。如果该函数将与一组对象一起使用,则需要'set'(在设置val的行上)。
编辑:我从来没有注意到基于对象和基于值的Exists()函数的不同要求。我很少将集合用于非对象,但这似乎是一个完美的瓶颈,当我需要检查存在时,这个bug很难被追踪。如果错误处理程序已处于活动状态,则错误处理将失败,因此需要两个函数来获取新的错误范围。只需要调用Exists()函数:
Public Function Exists(col, index) As Boolean
On Error GoTo ExistsTryNonObject
Dim o As Object
Set o = col(index)
Exists = True
Exit Function
ExistsTryNonObject:
Exists = ExistsNonObject(col, index)
End Function
Private Function ExistsNonObject(col, index) As Boolean
On Error GoTo ExistsNonObjectErrorHandler
Dim v As Variant
v = col(index)
ExistsNonObject = True
Exit Function
ExistsNonObjectErrorHandler:
ExistsNonObject = False
End Function
并验证功能:
Public Sub TestExists()
Dim c As New Collection
Dim b As New Class1
c.Add "a string", "a"
c.Add b, "b"
Debug.Print "a", Exists(c, "a") ' True '
Debug.Print "b", Exists(c, "b") ' True '
Debug.Print "c", Exists(c, "c") ' False '
Debug.Print 1, Exists(c, 1) ' True '
Debug.Print 2, Exists(c, 2) ' True '
Debug.Print 3, Exists(c, 3) ' False '
End Sub
答案 2 :(得分:7)
我总是用这样的函数完成它:
public function keyExists(myCollection as collection, sKey as string) as Boolean
on error goto handleerror:
dim val as variant
val = myCollection(sKey)
keyExists = true
exit sub
handleerror:
keyExists = false
end function
答案 3 :(得分:5)
正如Thomas所指出的,你需要设置一个对象而不是Let。这是我的库中的一个通用函数,适用于值和对象类型:
Public Function Exists(ByVal key As Variant, ByRef col As Collection) As Boolean
'Returns True if item with key exists in collection
On Error Resume Next
Const ERR_OBJECT_TYPE As Long = 438
Dim item As Variant
'Try reach item by key
item = col.item(key)
'If no error occurred, key exists
If Err.Number = 0 Then
Exists = True
'In cases where error 438 is thrown, it is likely that
'the item does exist, but is an object that cannot be Let
ElseIf Err.Number = ERR_OBJECT_TYPE Then
'Try reach object by key
Set item = col.item(key)
'If an object was found, the key exists
If Not item Is Nothing Then
Exists = True
End If
End If
Err.Clear
End Function
正如Thomas所建议的那样,您可以将Collection类型更改为Object以对此进行概括。 .Item(key)语法由大多数集合类共享,因此实际上可能很有用。
编辑好像我被托马斯本人打得有点殴打。但是为了更容易重用,我个人更喜欢没有私有依赖的单个函数。
答案 4 :(得分:3)
使用错误处理程序来捕获Collection中不存在键时的情况可以使调试“中断所有错误”选项非常烦人。为了避免不必要的错误,我经常创建一个类,其中包含Collection中的存储对象和Dictionary中的所有键。字典存在(键)函数,所以我可以在尝试从集合中获取对象之前调用它。您只能在字典中存储字符串,因此如果您需要存储对象,仍然需要Collection。
答案 5 :(得分:3)
如果错误处理程序已经处于活动状态,则“错误处理将失败”语句只是部分正确。
您可以在日常工作中使用多个错误处理程序 因此,只能在一个功能中容纳相同的功能 只需重写您的代码:
Public Function Exists(col, index) As Boolean
Dim v As Variant
TryObject:
On Error GoTo ExistsTryObject
Set v = col(index)
Exists = True
Exit Function
TryNonObject:
On Error GoTo ExistsTryNonObject
v = col(index)
Exists = True
Exit Function
ExistsTryObject:
' This will reset your Err Handler
Resume TryNonObject
ExistsTryNonObject:
Exists = False
End Function
但是,如果您只将代码合并到例程的TryNonObject部分,则会产生相同的信息。
对象和非对象都会成功。
但是,它会加速非对象的代码,因为您只需要执行一个语句来断言该项目存在于集合中。
答案 6 :(得分:2)
更好的解决方案是编写TryGet函数。很多时候你要检查存在,然后获取该项目。通过同时这样做来节省时间。
public Function TryGet(key as string, col as collection) as Variant
on error goto errhandler
Set TryGet= col(key)
exit function
errhandler:
Set TryGet = nothing
end function
答案 7 :(得分:2)
见 http://www.visualbasic.happycodings.com/Other/code10.html 这里的实现具有以下优点:也可以选择返回找到的元素,并使用对象/本机类型(根据注释)。
由于链接不再可用,因此在此处转载:
确定集合中是否存在项目
以下代码显示如何确定集合中是否存在项目。
Option Explicit
'Purpose : Determines if an item already exists in a collection
'Inputs : oCollection The collection to test for the existance of the item
' vIndex The index of the item.
' [vItem] See Outputs
'Outputs : Returns True if the item already exists in the collection.
' [vItem] The value of the item, if it exists, else returns "empty".
'Notes :
'Example :
Function CollectionItemExists(vIndex As Variant, oCollection As Collection, Optional vItem As Variant) As Boolean
On Error GoTo ErrNotExist
'Clear output result
If IsObject(vItem) Then
Set vItem = Nothing
Else
vItem = Empty
End If
If VarType(vIndex) = vbString Then
'Test if item exists
If VarType(oCollection.Item(CStr(vIndex))) = vbObject Then
'Return an object
Set vItem = oCollection.Item(CStr(vIndex))
Else
'Return an standard variable
vItem = oCollection.Item(CStr(vIndex))
End If
Else
'Test if item exists
If VarType(oCollection.Item(Int(vIndex))) = vbObject Then
'Return an object
Set vItem = oCollection.Item(Int(vIndex))
Else
'Return an standard variable
vItem = oCollection.Item(Int(vIndex))
End If
End If
'Return success
CollectionItemExists = True
Exit Function
ErrNotExist:
CollectionItemExists = False
On Error GoTo 0
End Function
'Demonstration routine
Sub Test()
Dim oColl As New Collection, oValue As Variant
oColl.Add "red1", "KEYA"
oColl.Add "red2", "KEYB"
'Return the two items in the collection
Debug.Print CollectionItemExists("KEYA", oColl, oValue)
Debug.Print "Returned: " & oValue
Debug.Print "-----------"
Debug.Print CollectionItemExists(2, oColl, oValue)
Debug.Print "Returned: " & oValue
'Should fail
Debug.Print CollectionItemExists("KEYC", oColl, oValue)
Debug.Print "Returned: " & oValue
Set oColl = Nothing
End Sub
答案 8 :(得分:0)
在寻找这样的功能时,我将其设计如下。 这应该适用于对象和非对象而不分配新变量。
Public Function Exists(ByRef Col As Collection, ByVal Key) As Boolean
On Error GoTo KeyError
If Not Col(Key) Is Nothing Then
Exists = True
Else
Exists = False
End If
Exit Function
KeyError:
Err.Clear
Exists = False
End Function