Usar diccionarios en VBA de Microsoft Access 2010
Me ha encantado poder utilizar diccionarios en MS Access. Así puedo -por ejemplo- hacer que una función retorne más de un valor, pasar más de un parámetro a una función o simplemente guardar una colección de valores en formato clave:valor. Lo mejor de python en VBA.
Un diccionario es básicamente un objeto que contiene una lista de claves y valores. Por ejemplo:
"nombre": "Ruperto",
"apellidos": "Coronado"
Básicamente como un objeto de Javascript o tal cual, un diccionario en Python.
¿Cómo usar diccionarios en VBA?
Primero debes ir al menú de herramientas y seleccionar la opción de referencias. Luego en la ventana de referencias seleccionar la opción de Microsoft Scripting Runtime. Esto te permitirá utilizar diccionarios en VBA.
A partir de aquí ya puedes empezar a declar y usar diccionarios como en el siguiente ejemplo:
Public Sub ProbarDiccionarios()
Dim d as New Dictionay
d.Add "nombre", "Ruperto"
d.Add "apellidos", "Coronado"
Debug.Print d("nombre") ' Imprime "Ruperto"
Debug.Print d("apellidos") ' Imprime "Coronado"
'O puedes agregar directamente la clave:
d("edad") = 30
'Incluso puedes usar un subdiccionario
set d("habilidades") As New Dictionary
d("habilidades")("1") = "Programación"
'O mediante métodos
d("habilidades").add "2", "comer"
End Sub
¿Cómo recorrer (o iterar sobre) un diccionario?
Puede darse el caso en donde no conozcas las claves del diccionario o sencillamente tienes que iterarlo para hacer algunas operaciones
Public Sub IterarDiccionario()
Dim d as New Dictionay
Dim item as Variant
d.Add "nombre", "Ruperto"
d.Add "apellidos", "Coronado"
for each item in d
debug.print item, d(item) 'Imprime: clave:valor
next
end sub
¿Cómo hacer que una función retorne un diccionario en VBA?
Public Function ObtenerDiccionario() As Dictionary '<-- Esta es la clave
Dim d as New Dictionay
d.Add "nombre", "Ruperto"
d.Add "apellidos", "Coronado"
Set ObtenerDiccionario = d '<-- No olvides el Set que de otra manera no funcionará
End Function
Public Sub OperarDiccionario()
Dim d as Dictionary
Set d = ObtenerDiccionario()
dim item as Variant
for each item in d
debug.print item, d(item)
next
End Sub
Consideraciones importantes
Estos son los métodos que proporciona la clase Dictionary
Es muy importante saber que por defecto el método de comparación de claves está establecido en BinaryCompare
lo que hace que la comparación sea byte por byte por lo que será sensible a mayúsculas y minúsculas, de modo que d("hola")
y d("Hola")
podrian contener diferentes valores. Puedes establecerla en TextCompare
usando el método .CompareMode
También ten cuidado con el tipo de datos que tendrá la clave, porque sabes que 1<>“1”. Esto es especialmente importante cuando usas una variable del tipo Variant para establecer las claves del diccionario. Yo sugiero que siempre conviertas la clave a String antes de usarla.
Por ejemplo:
Private sub ProbarDiccionario()
Dim d as New Dictionary
d.Add "nombre", "Ruperto"
d.Add "apellidos", "Coronado"
d.add "1", "2"
debug.print d(1) 'Esto no funcionará porque la clave fue añadida como String
debug.print d("1") 'Esto sí
Dim intNumero as integer 'O cualquier otro tipo
intNumero = 1
d(intNumero) 'Esto no funcionara
d(CStr(intNumero)) 'Esto sí funcionará
'Por costumbre general cuando no sé el tipo de la variable que usaré para hacer referencia a una clave siempre uso CStr para convertirlo a String
End Sub
En este ejemplo asigno el contenido de un Recordset a un diccionario:
Sub ProbarDict()
Dim RS As New ADODB.Recordset
Dim d As Dictionary
Dim Campo As Variant
With RS
.Open "SELECT * FROM Producto", CurrentProject.Connection, adOpenStatic, adLockReadOnly
While Not .EOF
Set d(CStr(!ID)) = New Dictionary 'uso el ID como indice de elementos del diccionario
For Each Campo In .Fields
d(CStr(!ID))(CStr(Campo.Name)) = Campo.value
Next
.MoveNext
Wend
.Close
End With
Set RS = Nothing
Dim item As Variant
Dim subItem As Variant
Dim sD As Dictionary 'Sub diccionario que contiene los campos y valores de cada producto
'Imprimir los valores del diccionario
For Each item In d
Debug.Print "Producto ID: " & item
For Each subItem In d(item)
Debug.Print vbTab & subItem & ":" & d(item)(subItem)
Next
Next
'Se imprimirá:
'Producto ID: _
Nombre:JABON DE BARRA 200 GR _
Marca: ZOTE _
Precio: 15.00
End Sub
Por favor considera que es un ejemplo rápido y podría optimizarse más. Por ejemplo, podria detectarse el tipo de campo y asignar comillas a los valores cuando sean DATETIME o CHAR