sábado, 10 de diciembre de 2011

Asociar a un TextBox el valor seleccionado de un ListBox.

Seguiré hoy con el tema de los últimos días, esto es con Formularios (UserForm) en Excel. Hoy en concreto veremos como asociar a un TextBox el valor seleccionado de un ListBox, es decir, veremos cómo podemos desde un ListBox creado rellenar los TextBox o Cuadros de Texto incluidos en nuestro formulario; además aprenderemos una forma de Cambiar el nombre (propiedad Caption) de nuestras Etiquetas (Labels).
Partiremos del trabajo realizado en la entrada anterior (ListBox con varias columnas y encabezados), donde llegamos a este diseño:

VBA: ListBox con varias columnas y encabezados.


Accedemos al Editor de VB (Alt+F11) y dentro del Editor buscamos nuestro formulario UserForm1, activamos dicho formulario con lo que nos aparecerá el Cuadro de herramientas o controles. En este buscaremos los siguientes controles:
  1. Marco (Frame): con este delimitaremos, y haremos independiente de otros controles, lo que incluyamos en él.
  2. Etiquetas (Labels): no editable, para nombrar los Cuadros de texto que situaremos a su lado.
  3. Cuadro de Texto (TextBox): donde vincularemos los valores seleccionados en el Cuadro de Lista (ListBox).
Bien, en ese orden, primero seleccionaremos el área del marco(Frame), para luego colocar tres etiquetas(Labels) y a su lado respectivamente tres Cuadro de Texto (TextBox), asociando cada uno de éstos a una columna del Cuadro de Lista (ListBox) que tenemos ya creado.
El diseño nos quedaría así:

Asociar a un TextBox el valor seleccionado de un ListBox.


Una vez ha quedado acorde a nuestro control de calidad visual, podemos añadirle la funcionalidad buscada.
En primer lugar, modifcaremos ciertas propiedades de los diferentes controles incluidos en nuestro formulario. En concreto cambiaremos los nombres que se muestran en las tres etiquetas por la cabecera o rótulos de la tabla origen de datos, también asignaremos un nombre definido por nosotros al Marco (O Frame):

Sub UserForm_Initialize()
Dim fila As Single

'le decimos cuántas columnas tendrá
ListBox1.ColumnCount = 3
'que sí que tiene encabezado
ListBox1.ColumnHeads = True
'el origen de datos en nuestra hoja de cálculo
ListBox1.RowSource = "Tabla1"
'renombramos el Marco
Frame1.Caption = "Datos seleccionados:"
'damos nombre a las etiquetas creadas, empleando la cabecera de la Tabla1
fila = ListBox1.ListIndex + 2
With Hoja1.Range(ListBox1.RowSource)
    Label1.Caption = .Cells(fila, 1).Offset(-1, 0).Value
    Label2.Caption = .Cells(fila, 2).Offset(-1, 0).Value
    Label3.Caption = .Cells(fila, 3).Offset(-1, 0).Value
End With
End Sub



Observemos el resultado:


Ya sólo nos queda asignar una funcionalidad a nuestro Cuadro de Lista (ListBox1), y es que pretendemos que cada vez que seleccionemos un elemento de esa Lista, aparezca reflejado en los cuadros de texto, por supuesto, cada valor donde corresponda.
Esto lo conseguiremos con un evento click sobre el ListBox:

Private Sub ListBox1_Click()
fila = ListBox1.ListIndex + 2

    With Hoja1.Range(ListBox1.RowSource)
        TextBox1.Text = .Offset(ListBox1.ListIndex, 0).Resize(1, 1).Value
        TextBox2.Text = .Offset(ListBox1.ListIndex, 1).Resize(1, 1).Value
        TextBox3.Text = .Offset(ListBox1.ListIndex, 2).Resize(1, 1).Value
    End With
End Sub


Y listo, ya esta nuestro formulario operativo, podremos comprobar cómo en cada ocasión que marquemos de entre los elementos del ListBox, los valores de éste se mostrarán en los Cuadros de Texto (TextBox) habilitados.

Asociar a un TextBox el valor seleccionado de un ListBox.


Por último remarcar que, al estar vinculado directamente a los valores de la Hoja de cálculo, cualquier cambio o modificación en alguno de los datos de la Tabla1 se veré reflejado sobre nuestro formulario, incluyendo, por supuesto los nombres de las tres Etiquetas (Labels).

32 comentarios:

  1. Hola, Quisiera saber como hacer al contrario
    Elegir en un textbox y ubicarlo en un listbox

    ResponderEliminar
    Respuestas
    1. Hola Oscar,
      el tema es que un TextBox es un cuadro de texto donde escribir algo, no parece que tenga mucho sentido 'elegir' un elemento de un textbox, ya que en estos no es posible desplegar nada.
      Si te refieres a escribir algo en el textbox y luego añadirlo como elemento de un ListBox, tendrías que emplear la propiedad additem del listbox sobre el textbox.value.
      Slds

      Eliminar
  2. Hola, tengo una duda relacionado con los listbox.
    Tengo un listbox con una serie de números, entre ellos números decimales. Quiero copiar uno de los item (por ejemplo el item(2) que es 27,56) a un label.
    Cuando lo copio mediante la orden Label.Caption = Val(List3.List(1)) me sale en el label el valor 27 y no los decimales. ¿cómo puedo hacer para que aparezcan decimales?

    Gracias!

    ResponderEliminar
    Respuestas
    1. Hola Pedro,
      prueba con .Formula en lugar de .Value
      Label.Caption = Val(List3.List(1).Formula)
      si fallara, prueba con
      Label.Caption = Replace(Val(List3.List(1).value), ",", ".")

      Slds cordiales

      Eliminar
  3. me marca erro en la parte
    With Hoja1.Range(ListBox1.RowSource)
    en la palabra Range

    ResponderEliminar
    Respuestas
    1. Hola Noemi,
      un placer saludarte igualmente.
      Asegúrate que tus controles en el UserForm se llaman de igual forma (ListBox1), y que tienes una 'Hoja1' (fíjate en el codename de la hoja.. no en el nombre visble)
      Saludos

      Eliminar
    2. ok, entonces el nombre que tiene la etiqueta de la hoja no es el que se utiliza??
      Saludos

      Eliminar
    3. Las hojas pueden ser llamadas de varias formas, en particular utilizando el nombre de la 'etiqueta' (propiedad Name) o su nombre de código (propiedad codename).
      http://excelforo.blogspot.com.es/2013/08/vba-la-propiedad-codename-de-las-hojas.html

      Quizá tu problema sea ese.. estás intercambiando nombres.

      Verifica también el nombre del control (del ListBox)
      Saludos

      Eliminar
  4. Hola, espero que estén bien. Tampoco me funciona la hoja está bien referenciada y el texbox bien nombrado, cuando coloco la flecha sobre el with muestra el nombre de la tabla fuente del listbox, pero saca error de "se requiere objeto" gracias

    ResponderEliminar
    Respuestas
    1. Hola Carlos,
      supongo te refieres al código de este mismo post...
      Asegúrate que el CodeName de tu hoja corresponde con el de tu código.. en mi ejemplo, es 'Hoja1'.. quizá en tu caso se distinto o simplemente no exista..
      Saludos

      Eliminar
  5. Buenos dias, he estado tratando de trabajar con listas muy grandes, la validacion no me sirve porque no es predictiva y toca elegir uno por uno los datos, y el combobox tampoco porque tengo muchas lineas diferentes y tendria que insertar un combobox por cada linea donde quiero insertar un nombre.

    Navegando me consegui este ejemplo que podria solucionar todo pero no se como hacerlo pues no se explica muy bien y no tengo mucho conocmiento en VBA, en el ejemplo usan un textbox y un listbox, el textbox esta asociado a una lista ya creada y cuando se va escribiendo algo en el textbox me muestra en el listbox todas las opciones que hay en la lista, nada mas se elige cual es la que necesito y se inserta en cualquier celda donde esta ubicado en ese momento, es muy facil porque con uno solo que inserte me sirve para cuantos datos diferentes quiera incluir, solo cambiando de celda al momento de hacer la eleccion, te dejo el link para descargar el ejemplo a ver si me puedes ayudar sobre como crearlo, saludos y gracias http://www.mediafire.com/download/jmg5ginjnqn/ListaDesplegableConAutoAjuste.xls

    ResponderEliminar
    Respuestas
    1. Hola,
      la técnica de esto es emplear la herramienta de Filtro avanzado sobre la columna A (Nombres) de la Hoja de 'DAtos'.. el ListBox muestra el resultado obtenido de ese filtro.. esto es, se apoya en un Filtro para mostrar los valores resultantes que coinciden con lo escrito en el TextBox.

      Está asociado a un evento DoubleClick y Change de ambos controles...

      Lo que no sé es cómo puede serte útil si tienes que completar listas muy grandes de datos.. tendrías que replicar esos controles tantas veces como registros tuvieras...
      ?
      Saludos

      Eliminar
    2. Si me sirve porque con uno solo puedo introducir los elementos en cuantas celdas diferentes quiera, ya lo pude aplicar a mi hoja, pero el problema que tengo ahor es que el listbox se reduce de tamaño cada vez que le doy a un valor o que borro lo que escribi en el textbox para hacer una nueva busqueda, es normal que reduzca tamaño? como se arregla? en el ejmplo que use no pasa eso.

      Saludos...

      Eliminar
  6. Estoy intentando vaciar una base de datos desde datos capturados con un useform con textbox y listbox lo que no encuentro es como pasar esa seleccion del listbox a la base de datos en la respectiva posicion de la columna que le corresponde...

    ResponderEliminar
    Respuestas
    1. Hola Edwin,
      podrías emplear el método .Find en VBA para localizar el dato sobre tu hoja de cálculo, y una vez localizada ir rellenando celda a celda los elementos del ListBox.
      Saludos

      Eliminar
    2. decidi cambiar un poco la forma de captura y como era solo para elegir uno de dos item agreue un boton de opcion.... Ahora tengo otro problemita, prepare este codigo y corre bien al menos esta parte que es para buscar en una tabla partiendo de un valor en untextboxt y me los muestra en el mismo userfome en otrostextbox pero uno de esos textbox que carga quiero que lo muestre cuando aparecen el dato buscado con formato porcentul 0,00% y no se como, este es el codigo:
      Private Sub buscar_Click()


      Sheets("PROVEEDORES").Select
      Range("A:A").Select

      If buscar1 = "" Then
      MsgBox "Capturar datos"
      buscar1.SetFocus
      Exit Sub
      End If
      encontrado = False
      If IsNumeric(buscar1) Then
      valt1 = Val(buscar1.Value)
      Else
      valt1 = buscar1
      End If
      For i = 1 To Range("A" & Rows.Count).End(xlUp).Row
      If Cells(i, "A") = valt1 Then
      TextBox1 = Cells(i, "A")
      TextBox2 = Cells(i, "B")
      TextBox3 = Cells(i, "C")
      encontrado = True
      Exit For
      End If
      Next
      If encontrado = False Then
      MsgBox "Proveedor no Encontrado"
      End If
      End Sub

      Eliminar
    3. Hola,
      puedes aplicar la función format donde quieres conseguir ese formato porcentual:
      format(range("A1"),"0.00%")

      Saludos

      Eliminar
  7. Buenas tardes,

    Tengo una duda con respecto a como puedo enlazar un textbox con un combobox. Tengo una tabla en excel de meses de forma horizontal de enero a diciembre, del lado izquierdo tengo datos como código y proveedor, ahora bien una vez que activo mi userform que contiene un combobox donde hago aparecer todos los meses y textbox donde se agregará un valor de aporte, lo que necesito es saber como hace visual basic para que entienda que al seleccionar el mes en el combobox y agregue un valor en el textbox me lo lleve a la celda vacía del mes y si quisiera agregar un nuevo dato lo agregue en el espacio siguiente y así sucesivamente.

    Espero me pueda ayudar,

    Muchas Gracias!!

    ResponderEliminar
    Respuestas
    1. Hola,
      deberás realizar una búsqueda sobre los códigos dispuestos en la hoja, para localizar su fila a partir del valor del Combobox, una ve tengas localizada la fila y su posición de columna, podrás devolver el dato del TextBox con algo similar a esto:
      cells(fila,columna).value=textBox1.value
      en lugar de A2 deberás disponer de una variable par la fila y columna...

      espero aportarte la idea
      Saludos

      Eliminar
    2. Muchas gracias por responder,

      Lo que había hecho para tratar de solucionar el problema era esto:

      If ComboBox4.Text = "ENERO" Then
      Range("D2").Select
      ActiveCell.Offset(1, 0) = TextBox4.Value
      End If

      Pero resulta que el offset no realiza el trabajo de dirigir el segundo valor a la celda siguiente.

      Y a parte debía agregar por cada mes dicha instrucción, y sólo se almacena la información en la primera celda y no logra ingresar datos en las celdas siguientes.

      Gracias!!!

      Eliminar
    3. Hola,
      entiendo que en la hoja de cálculo, en tu columna D tienes los datos de ENERO, y quieres ir agregando nuevos datos uno debajo de otro..
      en ese caso:
      If ComboBox4.Text = "ENERO" Then
      Range("D"&rows.count).end(xlup).Offset(1, 0) = TextBox4.Value
      End If

      Saludos

      Eliminar
    4. Hola,

      Perfecto muchísimas gracias me sirvió muy bien.

      Saludos!!

      Eliminar
  8. amigo tengo un problema con el codigo al principio si funsiona bien cuando selecciono el primer registro pero si luego quiero cambiar a otro en el mismo listbox no me aparece el valor absoluto de lo que seleccione
    por ejemplo si selecciono el numero 164 la primera vez me lo pone en el textbox tal cal esta pero si despues selecciono el 165 solo me duvelve al textbox el 1 si lo selecciono de nuevo me devuelve el 6 y si lo vuelvo a hacer me devuelve el 5 que puedo hacer para que solo me devuelva el valor absoluto que sea completamente igal al del textbox

    ResponderEliminar
    Respuestas
    1. Hola Elin,
      no termino de entender el problema..
      Al añadir el evento click asociado al ListBox (ver post arriba) se gestionan los cambios y que cada vez que selecciones (hagas click) sobre un elemento lo muestre en los textbox...
      Es decir, el movimiento es desde el ListBox hacia el TextBox.
      Saludos

      Eliminar
  9. Hola Ismael. Tu código me ha servido de una forma maravillosa, pero necesito de tu ayuda para finalizar mi objetivo. Lo que quiero es que al momento de seleccionar con el primer click un item de un list box este me copie un dato a un text box (numero inicial de recibo para impresion), y al momento de seleccionar otro item me copie a otro text box el numero final de impresión. Mi problema esta en que no se como codificar el codigo que diferencie el primer click al segundo click para ordenar la seleccion, ademas de eso no se si se pueda con tu codigo o necesite de un multiselect diferente.

    ResponderEliminar
    Respuestas
    1. Hola,
      el problema es que no existe un evento de primer click o segundo click para ningún control...
      En todo caso podrías asociar la acción a si ha sido ya rellenado el primer textbox, esto es, al hacer click rellena el primer textbox (si está vacío), y al hacer otra vez click comprueba si el primer textbox está relleno y si lo está rellena el segundo...

      Espero te sirva la idea.

      Saludos

      Eliminar
    2. muchas gracias Ismael, no lo había pensado de esa manera y de verdad que me sirvió tu pensamiento. Gracias por tu tiempo eres un excelente maestro. Saludos desde Colombia.

      Eliminar
  10. Hola buenas tardes, tengo una duda tengo un listbox, quisiera que el valor que selecciono me aparesca en un combobox, se puede?

    ResponderEliminar
    Respuestas
    1. Hola,
      tendrías que cargar el item (.additem) al combobox y luego mostrarlo con combobox1.value
      Saludos cordiales

      Eliminar

Nota: solo los miembros de este blog pueden publicar comentarios.