【问题标题】:Check if a record exists in a VB6 collection?检查VB6集合中是否存在记录?
【发布时间】:2010-09-07 15:02:08
【问题描述】:

我在当前工作场所继承了一个大型 VB6 应用程序。我有点在工作中学习VB6,我遇到了很多问题。目前的主要问题是我无法弄清楚如何检查 Collection 对象中是否存在密钥。有人可以帮忙吗?

【问题讨论】:

    标签: vb6 collections


    【解决方案1】:

    http://www.visualbasic.happycodings.com/Other/code10.html 这里的实现的优点是还可以选择返回找到的元素,并且可以使用对象/本机类型(根据 cmets)。

    由于链接失效,在此转载:

    确定一个项目是否存在于集合中

    以下代码向您展示了如何确定一个项目是否存在于集合中。

    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
    

    【讨论】:

      【解决方案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
      

      【讨论】:

      • 为了避免这个问题,最好省略赋值部分,即去掉Set o = col(index) or v = col(index)指令和变量声明,简单写成col.item 索引,它与对象和简单值的作用相同。
      【解决方案3】:

      更好的解决方案是编写一个 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
      

      【讨论】:

        【解决方案4】:

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

        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
        

        【讨论】:

          【解决方案5】:

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

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

          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】:

            我的标准函数很简单。无论元素类型如何,这都将起作用,因为它不需要进行任何分配,它只是执行集合属性 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
            

            【讨论】:

              【解决方案7】:

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

              【讨论】:

              【解决方案8】:

              正如 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) 语法由大多数集合类共享,因此它实际上可能很有用。

              编辑 好像我被托马斯本人打败了。但是为了更容易重用,我个人更喜欢没有私有依赖的单个函数。

              【讨论】:

                【解决方案9】:

                我总是用这样的函数来完成它:

                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
                

                【讨论】:

                  猜你喜欢
                  • 1970-01-01
                  • 2011-02-20
                  • 2013-05-29
                  • 1970-01-01
                  • 1970-01-01
                  • 2015-01-21
                  • 2012-08-13
                  相关资源
                  最近更新 更多