2008-09-02 32 views
17

Heredé una gran aplicación VB6 en mi lugar de trabajo actual. Estoy aprendiendo VB6 en el trabajo y tengo varios problemas. El principal problema en este momento es que no puedo averiguar cómo verificar si existe una clave en un objeto Collection. ¿Alguien puede ayudar?¿Verifica si existe un registro en una colección VB6?

Respuesta

8

que siempre he hecho con una función como esta:

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

@ Marcos Biek Sus keyExists se acerque a mi nivel existe la función(). Para que la clase sea más útil para colecciones expuestas a COM y para verificar índices numéricos, recomiendo cambiar sKey y myCollection para que no se tipeen. Si la función se va a usar con una colección de objetos, se requiere 'set' (en la línea donde se establece val).

EDIT: Me molestaba saber que nunca había notado los diferentes requisitos para una función Exists() basada en objetos y basada en valores. Muy rara vez uso colecciones para objetos no-objetos, pero esto parecía un cuello de botella perfecto para un error que sería tan difícil de rastrear cuando necesitaba verificar la existencia. Debido a que el manejo de errores fallará si un manejador de errores ya está activo, se requieren dos funciones para obtener un nuevo alcance de error. Sólo la función existe() tiene por qué nunca se llamará:

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 

y verificar la funcionalidad:

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 
+1

Para evitar este problema, es mejor omitir la parte de asignación, es decir, la caída de las instrucciones establecidas o = col (índice) o v = col (índice) y la declaración de variables, y simplemente escribir col. índice de elemento, que funciona igual con objetos y valores simples. – Clon

+1

Ahora veo que esto ya fue demostrado por Christian Hayter – Clon

5

Como ha señalado Thomas, necesita configurar un objeto en lugar de Let. He aquí una función general de mi biblioteca que funciona para los tipos de valor y objetos:

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 

Como también se aconseja por Thomas, puede cambiar el tipo de colección a objeto de generalizar esto. La sintaxis de .Item (clave) es compartida por la mayoría de las clases de colección, por lo que en realidad podría ser útil.

EDIT Parece que el mismo Thomas me golpeó un poco. Sin embargo, para una reutilización más fácil, personalmente prefiero una única función sin dependencias privadas.

3

Usar el controlador de errores para detectar casos cuando la clave no existe en la Colección puede hacer que la depuración con la opción "interrumpir todos los errores" sea bastante molesta. Para evitar errores no deseados, muy a menudo creo una clase que tiene los objetos almacenados en una Colección y todas las claves en un Diccionario. El diccionario tiene una función (clave) para poder invocar eso antes de intentar obtener un objeto de la colección. Solo puede almacenar cadenas en un diccionario, por lo que aún se necesita una colección si necesita almacenar objetos.

+0

Eso no está bien: puedes almacenar cualquier tipo de objeto/valor en un Dictiionary https://msdn.microsoft.com/en-us/library/x4k5wbx4%28v= vs.84% 29.aspx "Los elementos pueden ser cualquier tipo de datos" – Clon

+0

Un diccionario simple es suficiente cuando lo único que desea es almacenar una cantidad de valores/objetos junto con una clave y verificar si existe una clave en el diccionario. Si desea asegurarse de que el diccionario contenga solo cierto tipo de datos, debe ajustar el diccionario a un objeto y personalizar sus propiedades y métodos. Esto también se puede hacer con un objeto Collection y el método Exists() dado en otras respuestas. https://msdn.microsoft.com/en-us/library/aa262338%28v=vs.60%29.aspx – Clon

2

La mejor solución sería escribir una función TryGet. Gran parte del tiempo que va a verificar existe y luego obtiene el artículo. Ahorre tiempo al hacerlo al mismo tiempo.

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

ver http://www.visualbasic.happycodings.com/Other/code10.html la implementación de aquí tiene también la ventaja de devolver opcionalmente el elemento que se encuentra, y trabaja con los tipos de objetos/nativos (de acuerdo con los comentarios).

reproducido aquí, ya que el enlace ya no está disponible:

determinar si existe un elemento en una colección

El código siguiente muestra cómo determinar si existe un elemento dentro de una colección.

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 
24

Mi función estándar es muy simple. Esto funcionará independientemente del tipo de elemento, ya que no molesta hacer ninguna asignación, simplemente ejecuta la obtención get de la propiedad.

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

Breve, rápido y efectivo. +1 punto – Clon

+0

¡Limpio, breve e inteligente! gracias –

+0

Ellegant. Esta es una buena lógica. +1. – Alex

3

La declaración "el manejo de errores fallará si un controlador de errores ya está activo" es parcialmente cierto.

Puede tener múltiples manejadores de errores dentro de su rutina.
Entonces, uno podría acomodar la misma funcionalidad en una sola función.
Sólo reescribir su código como este:

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 

Sin embargo, si usted fuera sólo para incorporar el código en la sección TryNonObject de la rutina, esto dió la misma información.
Será exitoso tanto para Objetos como para no objetos. Sin embargo, acelerará el código de los objetos que no son, ya que solo tendrías que realizar una única declaración para afirmar que el elemento existe dentro de la colección.

0

Mientras buscaba una función como esta, la diseñé de la siguiente manera. Esto debería funcionar con objetos y no objetos sin asignar nuevas variables.

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 
Cuestiones relacionadas