domingo, mayo 22, 2011

Validación de datos - Tamaño de la fuente de la lista desplegable

En la última semana tres lectores me han consultado sobre el mismo tema: el tamaño de la fuente en las listas desplegables creadas con validación de datos.

El tamaño de la fuente en estas listas está definido por defecto y no puede ser cambiado. Esto genera dos problemas:

1 – Algunos de los valores de la lista desplegable aparecen “cortados”



2 – Si el zoom de la hoja está por debajo del 100%, los valores puede llegar a ser casi ilegibles



En esta nota mostraré dos estrategias para solucionar estos problemas:

1 – usar eventos para cambiar el ancho de la columna que contiene la celda con la validación de datos y el nivel de zoom de la hoja;

2 – usar una combobox de la colección de controles ActiveX.

Partimos de esta situación donde tenemos una lista de departamentos de una empresa, que hemos incluido en el nombre definido “lstDepartamentos” y una lista desplegable en la celda E2. Las columnas A, B y C nos sirven como columnas auxiliares y en aplicaciones prácticas estarán ocultas. EL nivel de zoom es 80%




Solución con un evento simple.


La estrategia es programar un evento de manera que cuando el usuario seleccione la celda que contiene la lista (E2), el ancho de la columna E pase a ser 30 (antes del evento es 15) y el zoom será del 120%. Al seleccionar cualquier celda fuera de E2, el zoom vuelve a ser del 80% y el ancho de la columna 15.
En el módulo de la hoja correspondiente ponemos este código


Private Sub Worksheet_SelectionChange(ByVal Target As Range)
  
    If Target.Address = "$E$2" Then
        ActiveWindow.Zoom = 120
        Range("E2").ColumnWidth = 30
    Else
        Range("E2").ColumnWidth = 15
        ActiveWindow.Zoom = 80
    End If

End Sub






Solución con evento complejo


La estrategia es la misma que en la solución anterior, pero el ancho de la columna será fijado dinámicamente de acuerdo al valor de la lista más largo. Para esto creamos una función UDF (definida por el usuario) para determinar este valor y lo pasamos al código del evento


Private Sub Worksheet_SelectionChange(ByVal Target As Range)

    Dim iColWidth As Double
'
    iColWidth = max_len_in_range(Range("lstDepartamentos"))
      
    If Target.Address = "$E$2" Then
        ActiveWindow.Zoom = 120
        Target.ColumnWidth = iColWidth
    Else
        ActiveWindow.Zoom = 80
        Range("E2").ColumnWidth = 15
    End If

End Sub


Private Function max_len_in_range(rngList As Range)
    Dim iR As Long
    Dim tmpLen As Integer
  
    For iR = 2 To rngList.Count
        If Len(rngList(iR)) > Len(rngList(iR - 1)) Then
            tmpLen = Len(rngList(iR))
        End If
    Next iR
  
    max_len_in_range = tmpLen
  
End Function

Solución con ComboBox de la colección ActiveX


La ventaja de los controles ActiveX es que sus propiedades y sus eventos pueden ser programados. Esto nos permite “detectar” cuando el usuario activa el control y también cuando lo desactiva. Programamos un evento para cada una de las situaciones:


Private Sub ComboBox1_GotFocus()
    ActiveWindow.Zoom = 120
    Application.EnableEvents = False
    Me.Select
    Application.EnableEvents = True
End Sub

Private Sub ComboBox1_LostFocus()
ActiveWindow.Zoom = 80
End Sub


Los códigos hay que ponerlos en el módulo de la hoja correspondiente.

El archivo con los ejemplos se puede descargar aquí.


53 comentarios:

  1. Hola Joge

    Acabo de verlo...

    Está muy bueno. Lo tonto es que lo se hacer y no se me ocurrió aunque sea el evento simple.

    De todas formas muchísimas gracias por tu aporte desinteresado

    Como siempre muchos saludos

    Amadeo



    No es

    ResponderBorrar
  2. Jorge,

    Interesante y sencillas las soluciones, son buenos trucos que siempre resultan prácticos.
    Muchas gracias y felicitaciones nuevamente por el blog.

    Jean

    ResponderBorrar
  3. Hola

    Cómo hacer para que el ComboBox me devuelva valor y no un número en forma de texto?

    Lo obtengo de una tabla cuya 1º columna son nº y no textos.

    Saludándote atte estoy a la espera de una posible solución

    ResponderBorrar
  4. Hay varias soluciones posibles (evento, celda auxiliar con fórmula, convertir el texto en número dentro la fórmula que lo usa, etc.). Básicamente se trata de convertir el resultado de la combobox (texto) en número. Para evaluar la mejor solución tendría que conocer todo el contexto.
    Como tu consulta no está relacionada con el tema de la nbota, te sufgiero que sigamos la charla por mail privado.

    ResponderBorrar
  5. CUANDO DICES:"En el módulo de la hoja correspondiente ponemos este código"
    NO SÉ QUÉ ES EL MÓDULO PARA PONER EL CÓDIGO.
    AGRADECERÍA ME COMENTASES.
    MUY AGRADECIDO Juanjo

    ResponderBorrar
  6. Se trata del código del evento y éste va en el módulo de la hoja. Para acceder a ese módulo puedes hacer un clic con el botón derecho del mouse a la pestaña de la hoja y elegir la opción "ver código". En el blog hay varias notas sobre el tema eventos, ésta el la primera de la serie

    ResponderBorrar
  7. Hola!
    Este código no me funcionó en excel 2010. Qué cambios debo realizar para que funcione?.

    ResponderBorrar
  8. Bueno, como se puede ver en las imágenes, el ejemplo fue desarrollado en Excel 2010. Te sugiero qeu descargues el archivo con el ejemplo.

    ResponderBorrar
  9. Buenas Tardes, como cambiaría el tamaño de la lista desplegable de un Celda COMBINADA?

    ResponderBorrar
  10. ¿Te refieres a un cuadro combinado(combobox)? Si es el caso, hay dos tipos de controles: el cuadro combinado de la colección Formulario y el control ActiveX.
    En el primer caso cambiando el valor de "Lineas de unión verricals" en el cuadro de propiedades del control.
    En el control ActiveX se puede hacer manualmente cambiando el valor de la propiedad ListFillRows en el cuadro de propiedades o programando un evento que haga el cambio.

    ResponderBorrar
  11. Buenísimo! Creo que es lo que necesito. Gracias Jorge.
    Lo voy a intentar con excel 2010.
    Mi duda es si va a ser visible para gente que no tenga excel 2010, ni la opción de Programador, ni ActiveX...
    ¿Alquien sabría decirme?
    Un saludo!
    Patricia

    ResponderBorrar
  12. Patricia,
    también las versiones anteriores de Excel (2003, 200) incluyen los controles ActiveX y Vba (macros). Lo único que hay que asegurarse que el nivel de seguridad permita correr macros.

    ResponderBorrar
  13. Gracias Jorge. ¡Enhorabuena por el blog! Lo recomendaré!!! Lástima que desde el trabajo el firewall no me deje entrar a blogspot...

    De momento no he conseguido que me haga zoom en toda una columna, pero sigo intentando.
    Patricia

    ResponderBorrar
  14. Gracias por tu ayuda, me gustaría saber si es posible que el zoom funcionara no solo en una celda en el ejemplo simple, sino en la columna entera, o un área determinada, me sería de gran ayuda.

    Gracias de antemano.

    ResponderBorrar
  15. Andrés, el zoom se aplica a toda la hoja; el cambio en el ancho se aplica a toda la columna. Esa es la forma en que Excel funciona, por eso no entiendo tu consulta.

    ResponderBorrar
  16. Disculpa tal vez me he expresado mal, quisiera que este zoom funcionara no solo al seleccionar en una celda, sino al seleccionar cualquiera de un determinado rango (por ejemplo cualquiera de una determinada columna donde están los desplegables en todas las celdas).

    Un saludo y gracias de antemano

    ResponderBorrar
  17. En la solución con el evento, en klugar de referirlo a una única celda con
    If Target.Address = "$E$2"
    tendríamos que referirlo a todo el rango. Por ejemplo para que se refiera a toda la columna E usamos

    If Target.Column = 5

    ResponderBorrar
  18. Jorge, tengo el mismo problema que Andrés solo que necesito que el zoom se active en tres rangos de celdas consecutivas de las columans F, G y H serian la columna 6, 7 y 8 pero solo me lo toma para la última es decir la 8

    ResponderBorrar
  19. No se cuál de las soluciones estás usando, pero en el evento simple tendrías que reemplazar la referencia a una única columna por una referencia a todo el rango de las tres columnas. Por ejemplo

    Private Sub Worksheet_SelectionChange(ByVal Target As Range)

    If Union(Target, Range("F:H")).Column = Range("F:H").Column Then
    ActiveWindow.Zoom = 120
    Range("F:H").ColumnWidth = 25
    Else
    ActiveWindow.Zoom = 80
    Range("F:H").ColumnWidth = 15
    End If

    End Sub

    ResponderBorrar
  20. Buen día Jorge, existe alguna manera de que en vez de colocar el código que comentaste la ultima vez en "el módulo de la hoja correspondiente" es decir, hoja por hoja, se pueda colocar en "ThisWorkbook" para que haga referencia a todas las hojas del libro, sin necesidad de estar copiando dicho código hoja por hoja?

    Private Sub Worksheet_SelectionChange(ByVal Target As Range)

    If Union(Target, Range("F:H")).Column = Range("F:H").Column Then
    ActiveWindow.Zoom = 120
    Range("F:H").ColumnWidth = 25
    Else
    ActiveWindow.Zoom = 80
    Range("F:H").ColumnWidth = 15
    End If

    End Sub

    ResponderBorrar
  21. Hola me pareció muy funcional e interesante, ahora mi duda es: ¿cómo aplico el evento para diversas listas? ejemplo: tengo una lista de validación de datos en F5 y tengo otra en D2 y quizás otra en J8, ¿cómo hacer que el evento aplique con las 3 listas al seleccionarlas cada una?

    ResponderBorrar
  22. Se puede repetir dentro del evento el código para cada celda o usar Or

    If Target.Address = "$E$2" Or Target.Address="$D$2 Or...Then

    ResponderBorrar
  23. Podria desarrollar el ejemplo If Target.Address = "$E$2" Or Target.Address="$D$2 Or...Then , soy nueva en esto de VB y me esta dando un error de no coincide tipo y ni idea

    ResponderBorrar
  24. disculpa el codigo es genial y sencillo pero cuando es un renglon que tiene dos por ejemplo estas en el renglon E2 Pero ese renglon le aplique marge & center fucione lo que era el E2 y E3 y no funciona el primer codigo creas poder ayudarme

    ResponderBorrar
  25. Hola Enrique, una de las reglas de buenas prácticas en Excel es evitar el uso combinar y centrar (merge & center). Fijate en esta nota.
    Existen alternativas al uso de combinar y centrar, por ejemplo usar "centrar en la selección" en el menú Formato de Celdas – Alineación.
    Si no puedes evitar el uso de combinar y centrar, puedes fijarte en esta nota donde propongo una solución con Vba.

    ResponderBorrar
  26. Gracias "Jorge" por el buen consejo y lo tomare de ahora en adelante, pues todo funciona exelente en las NOTAS que dejaste el problema es que ya teno muy abansado mi reporte y si son demaciadas celdas combinada en uno de los comentarios aqui das un codigo que es para toda la fila ese funciona pero cres que podrian ser para ciertos numero de renglones por ejemplo que fuera de ( E2 , E8 )

    de antemano gracias por el consejo y si no se puede hacer nada con la pena pero are todo otrabes hahahahaha Gracias

    ResponderBorrar
  27. A y disculpa tendras un correo al que te pueda enviar una consulta distinta a este tema te lo agradeceria

    ResponderBorrar
  28. Hola Enrique, en la parte superior del blog hay un botón "Ayuda". Ahí podrás leer las condiciones para solicitar ayuda y ver mi dirección.
    Una pregunta sin ningún ánimo de ofender (sinceramente y se te ofende me disculpo de antemano): todos los errores de ortografía en tu comentario ¿son intencionales o se trata de errores de tipeo?

    ResponderBorrar
  29. Hola, muy bueno tu codigo. Queria saber cmo lo aplicaria para un conjunto de celdas. Ya sea una columna de "n" celdas, una fila de "m celdas o una matriz de "nxm" celdas.
    Estaré muy agradecido. Gracias,

    ResponderBorrar
  30. Jhon, en el código del evento sencillo, por ejemplo, en lugar de

    If Target.Address = "$E$2"

    ponemos

    If union(target,range("A1:C10")).address=range("A1:C10").address then

    Esto hace que el evento responda a cambios en el rango A1:C10. Si queremos limitar el evento a determinadas celdas de una fila, por ejemplo A1;Z1, usamos range("A1:C10").

    ResponderBorrar
  31. Muchas gracias Jorge por tu aporte.
    Saludos cordiales.

    ResponderBorrar
  32. Buenas tardes Jorge.
    Me resuelve las necesidades que tengo pero necesito que la solución de evento complejo sea aplicable a todas las celdas de una columna.
    Soy neófito y me estoy volviendo loco para intentar añadirlo a tu código.
    Puedes ayudarme??

    ResponderBorrar
  33. Hola Carlos, supongo que descargaste el archivo con el ejemplo. En el evento complejo el código calcula primero el ancho máximo de los valores de la lista de departamentos (el rango A3:A8 en la hoja) y de acuerdo a este valor determina el ancho de toda la columna. El evento corre cuando se selecciona la celda E2.
    Si quieres que se aplique a toda la columna E, por ejemplo, tenés que hacer esta modificación

    If Target.Column = 5 Then
    ActiveWindow.Zoom = 120
    -----------

    ResponderBorrar
  34. Buenas tardes Jorge.
    Perdóname pero siguiendo las consultas de otros compañeros he podido aprender esto y alguna otra cosa con posterioridad al envió de la consulta.
    Felicidades por el blog y por enseñarnos a optimizar nuestro tiempo gracias a tu conocimiento.
    Seguimos en contacto.

    ResponderBorrar
  35. Buenas tardes Jorge.
    Te plante cuestiones en las distintas líneas del código del evento complejo.

    Dim iColWidth As Double
    '
    iColWidth = max_len_in_range(Range("lstDepartamentos"))
    En esta parte del código necesito poder indicar distintas listas de una hoja excel. Como uno varias listas??. Como indico la celda donde está indicada la lista??

    If Target.Column = 18 Or Target.Column = 27 Then
    En esta parte del código debo aplicarlo a 8 columnas. Hay alguna forma de nombrarlas todas sin necesidad de repetir el código 8 veces.
    ActiveWindow.Zoom = 120
    Target.ColumnWidth = iColWidth
    Else
    ActiveWindow.Zoom = 80
    Range("E2").ColumnWidth = 15
    Jorge como puedo decirle que respete la medida que tienen las celdas en el diseño de la hoja, que no es siempre la misma?? No es siempre 15, por ejemplo.
    End If

    Jorge si quieres que te envié la hoja de excel que estoy preparando lo hago sin problemas para la empresa.


    ResponderBorrar
  36. Carlos, te sugiero que sigamos la consulta por mail privado (fijate en el enlace Ayuda, en la parte supeior del blog).

    ResponderBorrar
  37. buen blog Jorge desde el 2016!

    ResponderBorrar
  38. que buen blog, me sacaste de un apuro. Muchas gracias!!!

    ResponderBorrar
  39. Felicitaciones por tu blog. Muchas gracias por tus aportes

    ResponderBorrar
  40. Hola, felicitaciones por su blog, tengo una consulta, si necesito aplicar la ampliación y reducción a un grupo de celdas en una columna y también a otras columnas como puedo modificar, el primer código para un evento simple. Ya que he intentado varias veces y no me sale.
    Muchas gracias por su ayuda.

    Saludos!

    ResponderBorrar
  41. Audrey, por ejemplo, si quisiéramos aplicar el evento al rango E2:E10, usaríamos este código

    Private Sub Worksheet_SelectionChange(ByVal Target As Range)

    If Union(Target, Range("E2:E10")).Address = Range("E2:E10").Address Then
    ActiveWindow.Zoom = 120
    Target.ColumnWidth = 30
    Else
    Target.ColumnWidth = 15
    ActiveWindow.Zoom = 80
    End If

    End Sub

    Aquí usamos la funcion Union de Vba para definir si la celda elegida (Target) se encuentra dentro del rango definido (E2:E10).

    ResponderBorrar
  42. Muchas gracias por su ayuda. Voy a aplicarlo. Que tenga buen día!

    ResponderBorrar
  43. Funcionó perfectamente. Muchas gracias, quería saber si quiero hacerlo para varias columnas como lo puedo escribir. Ya que me sale un error de la manera como lo estoy haciendo. Gracias

    ResponderBorrar
  44. Buen día jorge

    El ultimo ejemplo que le diste a Lynn Audrey me funciono de maravilla, pero ¡si tengo que hacer lo mismo con mas de un rango de celdas de la misma hoja como lo hago?

    ResponderBorrar
  45. Buen día jorge

    El ultimo ejemplo que le diste a Lynn Audrey me funciono de maravilla, pero ¡si tengo que hacer lo mismo con mas de un rango de celdas de la misma hoja como lo hago?
    por ejemplo activar zoom de 85 a los rangos M27:N28 y Y10:AD12

    ResponderBorrar
  46. Tendrás que modificar esta parte del código
    If Union(Target, Range("E2:E10")).Address = Range("E2:E10").Address Then...
    para que incluya los rangos, quedando de esta manera
    If Union(Target, Range("M27:N28,Y10:AD12")).Address = Range("M27:N28,Y10:AD12").Address Then...

    ResponderBorrar
  47. Buen día Jorge
    Muchas gracias por tu ayuda me funcionó perfecto, tengo otra consulta pero no tiene que ver con tu explicación, pero agradecería mucho tu ayuda.
    Tengo una situación donde requiero inspeccionar los cambio en los datos registrados y que se registre la fecha y hora en que se realiza el cambio, este es el código que utilizo:
    Private Sub Worksheet_Change(ByVal Target As Range)
    Application.MoveAfterReturn = True
    If Target.Count = 1 Then
    If Not Intersect(Target, Range("C17:C56")) Is Nothing Then
    Cells(Target.Row, "F") = Now
    End If
    End If
    End Sub
    Ahora requiero hacer lo mismo con mas rangos de celdas "L17:L56,U17:U56" y que la fecha queden registradas en las filas "O y X" respectivamente.
    Agradezco todo el soporte que me puedas brindar.

    Att: Javier Bejarano

    ResponderBorrar
  48. Javier,

    te sugiero que veas este post en mi blog y la continuación en este post.

    ResponderBorrar
  49. Hola Sr. Jorge L. Dunkelman. su primera solucion no me permite usar una macros que grabe para limpiar datos. (clearcontents), quite el codigo que pone de ejemplo en el modulo de la hoja y la macro de limpieza si me funciono. Sabra porque pasa esto? Necesito ampliar la celda de la lista desplegable. Ayuda porfavor

    ResponderBorrar
  50. Como seguramente comprenderás no puedo darte un respuesta sin ver el código que grabaste y el entorno en que se trabaja.

    ResponderBorrar
  51. Estimado Jorge.

    Necesito ampliar el tamaño del Zoom de una lista de validación.La cual está en la pestaña llamada FORMATO, columna L20.
    Usé los códigos que aparecen en los primeros post, pero no me resultan.
    La lista de los datos (de la que se obtiene la lista de validación) está en otra pestaña, llamada Maestra, en la columna denominada "Código_Sección"
    ¿Cómo puedo hacrlo?

    ResponderBorrar
  52. Estimado, tenés que asegurarte de poner los códigos en el módulo de la hoja correspondiente y también de ajustar las variables (en el ejemplo el código se dipara cuando la celda seleccionada es E2; en tu caso hay que poner el rango adecuado).

    ResponderBorrar

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