Esta entrada es técnica sobre el uso del objeto combo en VBA y en VB6, y que ha surgido a raiz de realizar recientemente una pequeña aplicación en Excel que requería completar un combo con los datos de una tabla. El motivo fundamental de la misma es comprobar la diferente forma de preparar un combo, a partir de un recordset obtenido de una tabla.
Normalmente, en VB6, se emplea la propiedad ItemData para almacenar ahí el valor del ID, aunque se muestre su descripción. Para conectar con la base de datos he empleado oCon, que es un objeto ADODB.Connection, configurado como global para todo el módulo.
Private Sub EjemploCargaComboVB6()
Dim rs As ADODB.Recordset, sSQL As String, i As Integer
sSQL = "SELECT id, descripcion FROM tabla"
Set rs = oCon.Execute(sSQL)
If rs.EOF Then
' Sin Registros
GoTo Ending
End If
rs.MoveFirst
Me.combo.Clear ' Limpio el combo
Do While Not rs.EOF
Me.combo.AddItem rs.Fields("descripcion")
Me.combo.ItemData(me.combo.NewIndex) = rs.Fields("id")
rs.MoveNext
Loop
Ending:
End Sub
Para recuperar un valor del combo, utilizamos también ItemData, tal que así:
Private Sub combo_Click()
'Debug.Print Me.combo.ItemData(Me.combo.ListIndex)
End Sub
Combos en VBA
Sin embargo, en VBA de Excel (y también para el de Access también), no encontré dicha propiedad ItemData. La alternativa que he encontrado para trabajar de la misma forma es la siguiente:
Private Sub EjemploCargaComboVBA()
Dim rs As ADODB.Recordset, sSQL As String, i As Integer
sSQL = "SELECT id, descripcion FROM tabla"
Set rs = oCon.Execute(sSQL)
If rs.EOF Then
' Sin Registros
GoTo Ending
End If
rs.MoveFirst
Me.combo.Clear ' Limpio el combo
Me.combo.ColumnCount = 2
Me.combo.ColumnWidths = "0;150"
Me.combo.TextColumn = 2
Do While Not rs.EOF
Me.combo.AddItem rs.Fields("descripcion")
Me.combo.List(i, 1) = rs.Fields("descripcion")
Me.combo.List(i, 0) = rs.Fields("id")
i = i + 1
rs.MoveNext
Loop
Ending:
End Sub
La forma de “copiar” la propiedad ItemData consiste en crear un combo de múltiples columnas, en este caso 2, donde a una se le da un ancho, y a la otra ancho 0 (por tanto, no visible). Mediante un bucle se completan ambas columnas. Es una forma un poco más engorrosa, pero igual de efectiva!
Para recuperar un valor:
Private Sub combo_Click()
'Debug.Print Me.combo.List(Me.combo.ListIndex, 0)
End Sub
Espero que os sea de utilidad!