miércoles, octubre 01, 2008

Agregando valores a un cuadro combinado (ComboBox).

Después de publicar mi nota sobre autocompletar en Validación de Datos, algunos lectores me señalan que no logran encontrar la propiedad ListFillRange donde tienen que poner la referencia al rango que contiene los valores de la lista desplegable. Esto tanto con el control cuadro combinado como con el control cuadro de lista.

Existen ciertas diferencias entre los controles que agregamos directamente en una hoja de Excel y aquellos que agregamos a un UserForm en el editor de Visual Basic.

Cuando ponemos un control ActiveX directamente en la hoja vemos las propiedades del control activando el modo Diseño y abriendo el cuadro de propiedades (ambos iconos aparecen en la barra de Cuadro de Controles). Todo esto lo hemos mostrado en la nota mencionada.



Cuando creamos un cuadro combinado (ComboBox) o cuadro de lista (ListBox) sobre un Userform tenemos que activar el panel de propiedades del editor de Vb (VBE) para ver las propiedades




La propiedad que define los valores de cuadro o de la lista es RowSource. Para agregar valores al cuadro podemos usar una referencia a un rango en una hoja de Excel o podemos hacerlo usando código Vba.

Para ejemplificar el primer caso supongamos que en rango A1:A12 de la Hoja1 tenemos una lista de los meses del año, que podemos crear fácilmente con el menú Opciones-Listas Personalizadas.
En la propiedad RowSource del control ComboBox1 ponemos la referencia, con la sintaxis apropiada (ver el signo de exclamación entre el nombre de la hoja y la referencia al rango)



Para comprobar si nuestro control ha recibido los valores, seleccionamos el UserForm y apretamos F5. El UserForm aparecerá en la hoja activa (en realidad "sobre" la hoja) y podemos apretar la flecha para ver los valores disponibles



Otra posibilidad es agregar los valores usando programación. También aquí se nos abren dos posibilidades.
Si los valores se encuentran en un rango de una hoja, como en el caso que acabamos de mostrar, podemos usar un código como éste

Sub agregar_valores()

UserForm1.ComboBox1.RowSource = "Hoja1!A1:A12"

UserForm1.Show
End Sub


Al correr esta macro se abre el UserForm y podemos ver que los valores son los del rango.
Otra posibilidad es agregar los valores usando el método Add Item de Vba:

Sub add_val()
With UserForm1.ComboBox1
.RowSource = " "
.AddItem "Enero"
.AddItem "Febrero"
.AddItem "Marzo"
.AddItem "Abril"
.AddItem "Mayo"
.AddItem "Junio"
.AddItem "Julio"
.AddItem "Agosto"
.AddItem "Setiembre"
.AddItem "Octubre"
.AddItem "Noviembre"
.AddItem "Diciembre"
End With

UserForm1.Show
End Sub


En resumen, el manejo de las propiedades de los controles es distinto dependiendo si los hemos creado directamente en la hoja con la barra de Controles o han sido programados con Visual Basic.



Technorati Tags:

48 comentarios:

  1. Hola,

    Me ha servido mucho la información de tu blog, lo encuentro muy bueno.

    Quisisera aprovechar la oportunidad para plantearte la siguiente consulta:

    El punto es que estoy trabajando con una listbox multiselección (control activex)y necesito ingresar en la celda activa más de un valor. El siguiente código no me ha servido:

    Private Sub Proveedores_Click()
    ActiveCell.Value = Proveedores.Value
    End Sub


    ¿Me podrías guiar un poco?, te lo agradecería enormemente.

    Saludos y muchas gracias desde ya.
    Rodrigo

    ResponderBorrar
  2. Hola Rodrigo

    en una celda no puede haber más de un valor al mismo tiempo, ya sea texto, numérico, error o lógico.

    ResponderBorrar
  3. Hola, tu blog esta muy interesante, me ayuda mucho.

    He seguido los pasos que diste, pero me sale un herror, este dice:

    error de compilacion
    se esperaba fuction o una variable

    Gracias de ante mano por responder.

    ResponderBorrar
  4. Obviamente tienes un error de sintaxis. ¿Cuál de las dos rutinas estás intentando usar?

    ResponderBorrar
  5. Estimado Jorge, tu blog me ha servido montones para mejorar ciertos procesos que involucran muchos datos y requieren precisión en mi trabajo. Gracias por poner tus conocimientos a nuestra disposición.

    El sr. anónimo (igual que yo), está en lo correcto y hay dos errores en la sintaxis del ejemplo: poner "=" después de AddItem, y la propiedad RowSource no lleva punto antes.

    Saludos cordiales

    ResponderBorrar
  6. Estimado Anónimo

    gracias por llamar mi atención sobre los errores. En realidad hay uno, después de AddItem no va "=" sino directamente el nombre del mes entre comillas. El punto antes de RowSurce es necesario para que Vba no lo interprete como variable.

    ResponderBorrar
  7. Se puede dar como nombre de una hoja, una formula o una celda ... por ejemplo =A1 ?
    Seguro que hay alguna manera però no consigo encontrar-lo

    ResponderBorrar
  8. ¿Tal vez te refieres a poner el contenido de la celda o el resultado de fórmula como nombre?
    Excel es muy flexible con los nombres de las hojas. Las únicas limitaciones que conozco (o que me acuerdo en este momento) son que las hojas no pueden tener nombres con más de 31 caracteres y que no se puede usar ":" (dos puntos).
    Manualmente puedes ingresar toda combinación de caracteres que cumpla con las dos reglas indicadas.
    Para cambiar el nombre automáticamente tienes que usar Vba (macro).
    Esta orden cambia el nombre de la celda de acuerdo al contenido de la celda A1 de la hoja

    ActiveSheet.Name = [A1].Value

    A1 puede contener una constante o una fórmula.

    ResponderBorrar
  9. Buenos días,

    Hace ya días de esta entrada en el blog, pero me ha surgido hoy la duda y no encuentro por ninguna parte la solución. Siendo que para mi este site es toda una biblia (hay respuestas para todo), quisiera saber lo siguiente:

    Es posible asignar a un rowsurce el nombre que tengo asignado a un rango?
    Quiero decir: Yo tengo un rango que se llama "Existencias" y quiero asignar a un listbox ese rango que lo tengo como variable.
    He escrito:

    Listbox1.rowsource = existencias

    Pero me da error: No coinciden los tipos

    Habría posibilidad alguna de hacer esto??

    Un saludo

    Cristina

    ResponderBorrar
  10. Cristina

    para que VBa entienda que se trata de un nombre, tenés que usar

    Listbox1.rowsource = Range("existencias")

    ResponderBorrar
  11. Muy bueno, gracias me es de mucha ayuda tu blog

    ResponderBorrar
  12. Buen día,

    Jorge Muchas Gracias por todas las publicaciones...

    En relación a ésto, como puedo hacer si un Segundo ComboBox depende del valor que haya puesto en el primero?.

    Algo así como la función indirecto en la validación de datos en excel.

    José Angel

    Saludos

    ResponderBorrar
  13. Tendrías que hacerlo con programación (Vba).

    ResponderBorrar
  14. Disculpen como haría para que una vez creado un combo box con la lista que yo deseo, el resultado de mi elección sea enviado a una celda de excel especifica????

    ResponderBorrar
  15. Programando un evento (Vba, macros) o usando el valor de la celda ligada como argumento en una fórmula que combine INDICE y COINCIDIR.

    ResponderBorrar
  16. Mi problema es este:
    Frm_Vtas.Cbo_Empresa.Clear
    Frm_Vtas.Cbo_Empresa.ColumnCount = 2
    Frm_Vtas.Cbo_Empresa.MatchEntry = 1
    Frm_Vtas.Cbo_Empresa.ColumnHeads = False
    Frm_Vtas.Cbo_Empresa.BoundColumn = 1
    Frm_Vtas.Cbo_Empresa.ColumnWidths = "210;80"

    Frm_Vtas.Cbo_Empresa.ListIndex = -1

    Cadena = "Bd_Compania!D2:E" +
    Trim(Str(Bd_Compania.Range("b3").Value + 1))

    Frm_Vtas.Cbo_Empresa.RowSource = Cadena


    Me sales como error: 2No se puede configurar la propiedad recordsource. Valor de propiedad no valido.

    ResponderBorrar
  17. RowSource tiene que ser una cadena de texto. Comprobá el valor de Cadena, no me parece que resulte en un texto que represente un rango.

    ResponderBorrar
  18. Hola Jorge.

    Quisiera saber como puedo lograr que el rango de entrada de datos del combobox sea dinámico, a partir de información de una hoja.

    Gracias

    ResponderBorrar
  19. Hay varias formas de hacerlo. La más cómoda es usando nombres definidos. Por ejemplo, supongamos que los valores están en un rango que empieza en la celda A1 de la Hoja1. Podemos definir el nombre "rango_dinamico" (o culaquier otro nombre) que se refiera a la fórmula:

    =Hoja1!$A$1:INDICE($A:$A,CONTARA($A:$A))

    Luego en el cuadro de propiedades del control, en la propiedad ListFillRange ponemos rango_dinamico.

    ResponderBorrar
  20. Muy buena la ayuda, la otra forma de hacerlo seria seleccionando los datos, suponiendo de A1;A5 y en el cuadro de arriba a la izquierda deberiamos poner un nombre por ejmplo "Productos" y prewsionar Enter, depues en rownsource propiedades del combobox solo deberiamos colocar "Productos"( sin las comillas) y listo.

    ResponderBorrar
  21. muy buena la info del combobox pero me surge una pregunta y es un detallito que no he podido resolver sé y logre que con un combobox me mostrara los proovedores es mas no tan solo su numero de codigo sino tambien el nombre del proovedor en la seccion ColumnCount, hasta se puede hacer que se vean las encabezados de esas columnas en mi caso son 2 columnas y son A y B seria algo asi columna A=443434 y B=Empresa1, ahora bien cuando se selecciona un registro del combobox queda señalado la primera columna es decir el numero de codigo pero quiero y deseo almacenar en una variable el nombre correspondiente a ese codigo para luego su uso en otra parte que voy a necesitar espero sus prontas respuesta y espero me puedan ayudar de antemano mil gracias

    ResponderBorrar
  22. Tienes que usar la propiedad BoundColumn del control para determinar de que columna extraer el dato. Por ejemplo, si queremos pasar los valores a las celdas A1 y A2

    Private Sub cbAceptar_Click()

    'primero determinamos la columna y luego extraemos el valor
    With Userform1.ComboBox1
    .BoundColumn = 1
    Range("A1") = .Value
    .BoundColumn = 2
    Range("A2") = .Value
    End With

    Unload Userform1

    End Sub

    ResponderBorrar
  23. que tal mis Saludo tengo un pequeño problema excelente el Blog pero quisiera saber como ago para que la lista de valla actualizando al ingresar un nuevo elemento

    ResponderBorrar
  24. Usando rangos dinámicos. Puedes ver las notas del blog que tratan sobre el tema pulsando la etiqueta "rangos dinámicos" en la nube de etiquetas (en la parte superior de la plantilla).

    ResponderBorrar
  25. como puedo vincular 2 o mas cuadros combinados en visual para excel??

    ResponderBorrar
  26. Supongo que te refieres a que los valores de un cuadro dependan del valor elegido en el primero. Suponiendo que en un cuadro se elige el país y en el segundoo queremos que aparezcan las ciudades del país elegido, podrías crear nombres definidos (el nombre "argentina" se refiere al rango donde están las ciudades de la Argentina, etc.) y usar estos nombres en el código para definir el Row Source del segundo cuadro combinado.

    ResponderBorrar
  27. Buen dia Jorge!

    en base a una consulta anterior (como puedo hacer si un Segundo ComboBox depende del valor que haya puesto en el primero?), me podrias ayudar un poco mas?

    Gracias.

    ResponderBorrar
  28. Buen dia Jorge, mi problema es el siguiente:
    Dim strSql as string

    strSql = "Select campo1, campo2 from tabla"
    combo.ColumnCount = 2
    combo.Rowsource = strSql

    Me arroja el error: No se puede configurar la propiedad Rowsource. Valor de propiedad no valido.

    Aclaro que la conexion no la puse aqui por brevedad, pero la consulta arroja datos correctamente. Que me falta? toca ejecutar la cadena antes de asignarla al combo?

    ResponderBorrar
  29. La propiedad RowSource usa texto o un cadena de texto que representa la dirección de una rango. Las técnicas para agregar los valores son las que muestro en la nota.

    ResponderBorrar
  30. ...aahhh y olvide aclararlo, los resultados de la consulta en el combo, pero con los nombres de columna, habilitando la propiedad ColumnHeads a true........ es posible hacerlo?

    ResponderBorrar
  31. Usando un loop (rizo) para definir los items de la combo. Para ver los detalles de la técnica te sugiero que consultes en algunos de los muchos foros de Vba que hat, como VbaExpress por ejemplo.

    ResponderBorrar
  32. Hola Jorge.
    Tengo un problema, he realizado una hoja excel con varios cuadros combinados para hacer un formulario. Funcionan bien y se pueden escoger los datos, pero cuando guardas y vuelves a abrir no mantiene los campos elegidos.

    ResponderBorrar
  33. Eso pasa si estás usando el control de la colección Formularios y no tienes definida la celda ligada.

    ResponderBorrar
  34. Gracias Jorge! Solucionado. Te debo unas cañas.

    Fdo: Rubén

    ResponderBorrar
  35. buenas tardes jorge

    yo tengo la siguiente condicion en un formulario

    Private Sub UserForm_INITIALIZE()
    ComboBox2.RowSource = "Hoja1 !LISTA"
    End Sub

    lo que hace es traerme una lista de un rango de celdas de una hoja de excel denominadas como LISTA. Sin embargo esta lista puede cambiar de tamaño en el excel. es decir, al ejecutar otra macro me añade un elemento a la lista pero en el combobox no me ajusta el tamaño de la lista y me deja el ultimo elemeto por fuera. en este caso me toca salirme del formulario y volverlo a inicializar para que me los muestre completos en el combo. mi pregunta es si sabe alguna forma de que el tamaño de la lista del combobox se este ajustando automaticamente a medida que el cambie la cantidad de items del excel.

    agradezco su ayuda.

    ResponderBorrar
  36. Hola,

    la propiedad RowSource está definida por un texto que representa un rango. Es decir, en tu caso, el texto "Hoja1!Lista" representa el rango al que se refiere el nombre definido LISTA.
    Todo lo que hay que hacer es definir este nombre en forma dinámica, de manera que cuando se agreguen o quiten valores de la lista, esto se reflejen en el evento Initialize.
    Por ejemplo, si los valores de LISTA están en la columna A a partir de la celda A1, esta fórmula define el rango dinámicamente

    =Hoja1!$A$1:INDICE(Hoja1!$A:$A,CONTARA(Hoja1!$A:$A))

    ResponderBorrar
  37. hola buenas noches una pregunta.
    quiero trabajar en excel con un userfrom en este quiero teclear el nombre
    de un alumno y me aparezcan sus datos en el userfrom como lo hago
    mil gracias por la ayuda que me puedan dar :)

    ResponderBorrar
  38. Para hacerlo tienes que tener conocimientos básicos de Vba. Hay varios cursos en la internet como el de Ismael Romero (fijate en el banner an la columna derecha del blog).

    ResponderBorrar
  39. Hola Muchas gracias por la info, queria saber si puedes ayudarme con una consulta del mismo tema

    Tengo un Tabla creada con CTRL+T llamada "PART", la cual tiene 3 columnas con los encabezados "FAC", "COM" y "CAL" y tengo un combobox que depende del valor asignado a otro combobox, que despliega el nombre de los encabezados de la tabla "PART", el problema es que no encuentro la forma de asignar al RowSouce alguno de los siguientes valores "PART[FAC]", "PART[COM]" o "PART[CAL]"

    En VBA estoy intentando lo siguiente

    Private Sub ComboBox1_Change()

    UserForm1.Label12.Visible = True
    UserForm1.ComboBox6.Visible = True
    UserForm1.ComboBox6.RowSource = "PART[" & UF1.ComboBox6.Value & "]"

    End Sub

    Me podrías decir en donde la estoy regando?

    ResponderBorrar
  40. Hola Héctor

    para poder usar referencias a una Tabla tenés que crear primero un nombre definido que se refiera a ese rango. Luego podés usar el nombre en tu código.
    En tu caso digamos que creas tres nombres

    CAL que se refiere a =PART[CAL]
    COM que se refiere a =PART[COM]
    FAC que se refiere a =PART[FAC]

    El código del ComboBox1_Change() sería

    Me.ComboBox2.RowSource = Me.ComboBox1.Value

    ResponderBorrar
  41. Buena noche. he venido obsevando tu blog y me parece magnifica la colaboración que nos prestas con tus conocimientos. por eso muchas gracias.
    Tengo un problema con un cuadro combinado activex. y es que al capturar los valores de un rango que se compone de numeros telefonicos, y enviarlos a una celda que esta en otro libro, aparece el número indicado, solo que con formato de texto. y al querer usarlo para buscar otro dato de esa tabla con BUSCARV, no me funciona. y en otra hoja de calculo que ya tengo hecha, la cual hice con los mismos procedimientos no tengo este problema. los numeros los pega en la celda indicada y con formato de numero. si me pudieras ayudar con este asunto te estare altamente agradecido.

    ResponderBorrar
  42. Edy
    por favor, fijate lo que pongo en el enlace Ayuda (en la parte superior del blog) y ponte en contacto conmigo por mail privado.

    ResponderBorrar
  43. Hola a todos,
    Agradeceros antes que nada por vuestro gran trabajo.
    Os escribo porque tengo un problema que seguramente es más sencillo de lo que parece:
    Estoy intentando que el Combobox de un Formulario recoja la información de un Item de una tabla dinámica, y la verdad es que me estoy liando un poco entre los métodos y las clases PivotFiled y PivotItem. Si me pudieseis echar un cable con esto sería genial.

    Basicamente se trata de que el usuario final no tenga que manipular la Tabla dinámica y pueda correr el macro desde un formulario al que previamente se le ha señalado la fecha (que esta como Item de un campo de la Tabla)

    ResponderBorrar
  44. Mauro, por favor fijate lo que pongo en el enlace Ayuda (en la parte superior del blog) y ponte en contacto conmigo por mail privado.

    ResponderBorrar
  45. Hay algun condigo que al momento de ingresar al excel , el botón de opción(ActivexX), aparezca sin selecionar aún.

    ResponderBorrar
  46. En el cuadro de propiedades del objeto debes definir Value como False. T

    ResponderBorrar

Nota: sólo los miembros de este blog pueden publicar comentarios.