Проверить, существует ли запись в коллекции VB6? - PullRequest
17 голосов
/ 03 сентября 2008

Я унаследовал большое приложение VB6 на моем текущем рабочем месте. Я как бы изучаю VB6 на работе, и у меня есть ряд проблем. Главная проблема на данный момент - я не могу понять, как проверить, существует ли ключ в объекте Collection. Кто-нибудь может помочь?

Ответы [ 9 ]

26 голосов
/ 01 декабря 2009

Моя стандартная функция очень проста. Это будет работать независимо от типа элемента, так как он не требует выполнения какого-либо присваивания, он просто выполняет свойство коллекции 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
21 голосов
/ 03 сентября 2008

@ 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
7 голосов
/ 03 сентября 2008

Я всегда делал это с помощью такой функции:

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 голосов
/ 03 сентября 2008

Как указал Томас, вам нужно установить объект вместо 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

Как также советовал Томас, вы можете изменить тип Collection на Object, чтобы обобщить это. Синтаксис .Item (key) используется большинством классов коллекций, поэтому это может быть полезно.

РЕДАКТИРОВАТЬ Похоже, я был несколько избит ударом самого Томаса. Однако для более легкого повторного использования я лично предпочитаю одну функцию без частных зависимостей.

3 голосов
/ 02 марта 2012

Утверждение «обработка ошибок завершится ошибкой, если обработчик ошибок уже активен», верно только отчасти.

В вашей программе может быть несколько обработчиков ошибок.
Таким образом, одну и ту же функциональность можно разместить только в одной функции.
Просто перепишите свой код так:

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 подпрограммы, это даст ту же информацию.
Это удастся как для объектов, так и не-объектов. Однако это ускорит ваш код для не-объектов, поскольку вам нужно будет выполнить только один оператор, чтобы подтвердить, что элемент существует в коллекции.

3 голосов
/ 09 сентября 2008

Использование обработчика ошибок для отлова случаев, когда ключ не существует в Collection, может сделать отладку с опцией "break on all errors" довольно раздражающей. Чтобы избежать нежелательных ошибок, я часто создаю класс, в котором хранятся объекты в коллекции и все ключи в словаре. Словарь имеет (ключевую) -функцию, поэтому я могу позвонить, прежде чем пытаться получить объект из коллекции. Вы можете хранить строки только в словаре, поэтому коллекция все еще необходима, если вам нужно хранить объекты.

2 голосов
/ 01 декабря 2009

см 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
2 голосов
/ 19 мая 2009

Лучшим решением было бы написать функцию 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
0 голосов
/ 05 марта 2013

Когда я искал такую ​​функцию, я разработал ее следующим образом. Это должно работать с объектами и не объектами без назначения новых переменных.

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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...