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

20

我在现公司继承了一个庞大的VB6应用程序。我正在工作中学习VB6,但还遇到了许多问题。目前最大的问题是我无法弄清楚如何检查集合对象中是否存在某个键。能否有人提供帮助?

9个回答

32

我的标准函数非常简单。它可以适用于任何元素类型,因为它不会进行任何赋值,只会执行集合属性获取。

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

22

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

编辑:我从未注意到基于对象和基于值的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
为避免这个问题,最好省略赋值部分,也就是删除指令 Set o = col(index) 或 v = col(index) 以及变量声明,直接写 col.item index 即可,它对于对象和简单值都有效。 - Clon

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

5

正如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所建议的那样,您可以将Collection类型更改为Object以实现泛化。.Item(key)语法被大多数集合类共享,因此这可能非常有用。

编辑 看起来我被Thomas本人击败了。然而,为了更容易地重复使用,我个人更喜欢一个没有私有依赖关系的单个函数。


3

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


这不正确:您可以在字典中存储任何类型的对象/值。 https://msdn.microsoft.com/en-us/library/x4k5wbx4%28v=vs.84%29.aspx “项可以是任何形式的数据” - Clon
当您只想存储一些值/对象以及键,并检查字典中是否存在该键时,简单的字典就足够了。如果您想确保字典仅包含某种类型的数据,则必须将字典包装到对象中并个性化其属性和方法。这也可以使用集合对象和其他响应中提供的Exists()方法来完成。https://msdn.microsoft.com/en-us/library/aa262338%28v=vs.60%29.aspx - Clon

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


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

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

查看更多:https://web.archive.org/web/20140723190623/http://visualbasic.happycodings.com/other/code10.html#sthash.MlGE42VM.dpuf

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接