检查 VB6 集合中是否存在记录?

Check if a record exists in a VB6 collection?

提问人:user4315 提问时间:9/3/2008 更新时间:1/31/2017 访问量:66406

问:

我在我现在的工作场所继承了一个大型 VB6 应用程序。我在工作中学习 VB6,我遇到了许多问题。目前的主要问题是我无法弄清楚如何检查 Collection 对象中是否存在键。谁能帮忙?

VB6 集合

评论


答:

7赞 Mark Biek 9/3/2008 #1

我总是用这样的函数来做:

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
22赞 Tom Mayfield 9/3/2008 #2

@Mark Biek 您的 keyExists 与我的标准 Exists() 函数非常匹配。为了使该类对 COM 公开的集合和检查数字索引更有用,我建议将 sKey 和 myCollection 更改为不键入。如果该函数将与对象集合一起使用,则需要“set”(在设置 val 的行上)。

编辑:令我烦恼的是,我从未注意到基于对象和基于值的 Exists() 函数的不同要求。我很少对非对象使用集合,但对于一个错误来说,这似乎是一个完美的瓶颈,当我需要检查是否存在时,很难追踪它。由于如果错误处理程序已处于活动状态,则错误处理将失败,因此需要两个函数才能获取新的错误范围。只需要调用 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赞 Clon 6/24/2016
为了避免这个问题,最好省略赋值部分,即去掉指令 Set o = col(index) 或 v = col(index) 和变量声明,只需编写 col.item index,它的工作原理与对象和简单值相同。
5赞 jevakallio 9/3/2008 #3

正如 Thomas 所指出的,你需要 Set 一个对象而不是 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 所建议的那样,您可以将“集合类型”更改为“对象”以概括这一点。这。Item(key) 语法由大多数集合类共享,因此这实际上可能很有用。

编辑似乎我被托马斯本人打了一拳。但是,为了便于重用,我个人更喜欢没有私有依赖项的单个函数。

3赞 Kaniu 9/10/2008 #4

当集合中不存在键时,使用错误处理程序来捕获情况可能会使使用“中断所有错误”选项进行调试变得非常烦人。为了避免不必要的错误,我经常创建一个类,该类将存储的对象放在 Collection 中,将所有键放在 Dictionary 中。字典具有exists(key)-function,因此我可以在尝试从集合中获取对象之前调用它。您只能将字符串存储在 Dictionary 中,因此如果您需要存储对象,仍然需要 Collection。

评论

0赞 Clon 6/24/2016
这是不对的:您可以将任何类型的对象/值存储在字典中 msdn.microsoft.com/en-us/library/x4k5wbx4%28v=vs.84%29.aspx“项目可以是任何形式的数据”
0赞 Clon 6/24/2016
一个简单的字典就足够了,当你只想存储一些值/对象和一个键,并检查字典中是否存在一个键时。如果要确保 Dictionary 仅包含特定类型的数据,则必须将 Dictionary 包装到一个对象中,并对其属性和方法进行个性化设置。这也可以通过 Collection 对象和其他响应中给出的 Exists() 方法来完成。msdn.microsoft.com/en-us/library/aa262338%28v=vs.60%29.aspx
2赞 C S 5/19/2009 #5

更好的解决方案是编写一个 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
2赞 Vijay 12/1/2009 #6

请参阅此处的实现 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
32赞 Christian Hayter 12/1/2009 #7

我的标准函数非常简单。无论元素类型如何,这都将起作用,因为它不会费心做任何赋值,它只是执行集合属性 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
3赞 R. van Drie 3/2/2012 #8

“如果错误处理程序已处于活动状态,则错误处理将失败”这句话只有部分正确。

例程中可以有多个错误处理程序。
因此,只能在一个函数中容纳相同的功能。
只需像这样重写代码:

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 部分中,则将生成相同的信息。
对于对象和非对象,它都会成功。 但是,它将加快非对象的代码速度,因为您只需执行一个语句即可断言该项存在于集合中。

0赞 Martin 3/5/2013 #9

在寻找这样的功能时,我将其设计如下。 这应该适用于对象和非对象,而无需分配新变量。

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