poo para objetos modulos glosario funciones funcion diccionario declarar crear array vba dictionary data-structures vb6

para - ¿VBA tiene estructura de diccionario?



modulos vba excel (9)

A partir de la respuesta de cjrh , podemos construir una función Contains que no requiere etiquetas (no me gusta usar etiquetas).

Public Function Contains(Col As Collection, Key As String) As Boolean Contains = True On Error Resume Next err.Clear Col (Key) If err.Number <> 0 Then Contains = False err.Clear End If On Error GoTo 0 End Function

Para un proyecto mío, escribí un conjunto de funciones de ayuda para hacer que una Collection comporte más como un Dictionary . Todavía permite colecciones recursivas. Notarás que Key siempre es lo primero porque era obligatorio y tenía más sentido en mi implementación. También utilicé sólo teclas de String . Puedes volver a cambiarlo si quieres.

Conjunto

Cambié el nombre de este para establecer porque sobrescribirá los valores antiguos.

Private Sub cSet(ByRef Col As Collection, Key As String, Item As Variant) If (cHas(Col, Key)) Then Col.Remove Key Col.Add Array(Key, Item), Key End Sub

Obtener

El err es para objetos, ya que pasarías objetos usando set y variables sin. Creo que puedes verificar si es un objeto, pero me presionaron para obtener tiempo.

Private Function cGet(ByRef Col As Collection, Key As String) As Variant If Not cHas(Col, Key) Then Exit Function On Error Resume Next err.Clear Set cGet = Col(Key)(1) If err.Number = 13 Then err.Clear cGet = Col(Key)(1) End If On Error GoTo 0 If err.Number <> 0 Then Call err.raise(err.Number, err.Source, err.Description, err.HelpFile, err.HelpContext) End Function

Tiene

La razón de este post ...

Public Function cHas(Col As Collection, Key As String) As Boolean cHas = True On Error Resume Next err.Clear Col (Key) If err.Number <> 0 Then cHas = False err.Clear End If On Error GoTo 0 End Function

retirar

No lanza si no existe. Sólo se asegura de que sea eliminado.

Private Sub cRemove(ByRef Col As Collection, Key As String) If cHas(Col, Key) Then Col.Remove Key End Sub

Llaves

Obtener una serie de claves.

Private Function cKeys(ByRef Col As Collection) As String() Dim Initialized As Boolean Dim Keys() As String For Each Item In Col If Not Initialized Then ReDim Preserve Keys(0) Keys(UBound(Keys)) = Item(0) Initialized = True Else ReDim Preserve Keys(UBound(Keys) + 1) Keys(UBound(Keys)) = Item(0) End If Next Item cKeys = Keys End Function

¿VBA tiene estructura de diccionario? ¿Como clave <> matriz de valor?


El diccionario de ejecución de scripts parece tener un error que puede arruinar su diseño en etapas avanzadas.

Si el valor del diccionario es una matriz, no puede actualizar los valores de los elementos contenidos en la matriz a través de una referencia al diccionario.



Sí.

Establecer una referencia al tiempo de ejecución de MS Scripting (''Microsoft Scripting Runtime''). De acuerdo con el comentario de @ regjo, vaya a Herramientas-> Referencias y marque la casilla "Microsoft Scripting Runtime".

Crea una instancia de diccionario usando el código de abajo:

Set dict = CreateObject("Scripting.Dictionary")

o

Dim dict As New Scripting.Dictionary

Ejemplo de uso:

If Not dict.Exists(key) Then dict.Add key, value End If

No olvides configurar el diccionario en Nothing cuando hayas terminado de usarlo.

Set dict = Nothing


Si, por cualquier motivo, no puede instalar funciones adicionales en su Excel o no lo desea, también puede usar arreglos, al menos para problemas simples. Como WhatIsCapital pones el nombre del país y la función te devuelve su capital.

Sub arrays() Dim WhatIsCapital As String, Country As Array, Capital As Array, Answer As String WhatIsCapital = "Sweden" Country = Array("UK", "Sweden", "Germany", "France") Capital = Array("London", "Stockholm", "Berlin", "Paris") For i = 0 To 10 If WhatIsCapital = Country(i) Then Answer = Capital(i) Next i Debug.Print Answer End Sub



Un ejemplo de diccionario adicional que es útil para contener la frecuencia de aparición.

Fuera del bucle:

Dim dict As New Scripting.dictionary Dim MyVar as String

Dentro de un bucle:

''dictionary If dict.Exists(MyVar) Then dict.Item(MyVar) = dict.Item(MyVar) + 1 ''increment Else dict.Item(MyVar) = 1 ''set as 1st occurence End If

Para comprobar la frecuencia:

Dim i As Integer For i = 0 To dict.Count - 1 '' lower index 0 (instead of 1) Debug.Print dict.Items(i) & " " & dict.Keys(i) Next i


VBA no tiene una implementación interna de un diccionario, pero desde VBA aún puede usar el objeto de diccionario de MS Scripting Runtime Library.

Dim d Set d = CreateObject("Scripting.Dictionary") d.Add "a", "aaa" d.Add "b", "bbb" d.Add "c", "ccc" If d.Exists("c") Then MsgBox d("c") End If


VBA tiene el objeto de colección:

Dim c As Collection Set c = New Collection c.Add "Data1", "Key1" c.Add "Data2", "Key2" c.Add "Data3", "Key3" ''Insert data via key into cell A1 Range("A1").Value = c.Item("Key2")

El objeto Collection realiza búsquedas basadas en claves utilizando un hash, por lo que es rápido.

Puede usar una función Contains() para verificar si una colección en particular contiene una clave:

Public Function Contains(col As Collection, key As Variant) As Boolean On Error Resume Next col(key) '' Just try it. If it fails, Err.Number will be nonzero. Contains = (Err.Number = 0) Err.Clear End Function

Edición 24 de junio de 2015 : Shorter Contains() gracias a @TWiStErRob.

Edición 25 de septiembre de 2015 : Se agregó Err.Clear() gracias a @scipilot.