lunes, 25 de octubre de 2010

Macro VBA -selectionchange: Cambio color y tamaño celda.

Me ha llegado una cuestión sobre la manera de remarcar con un color y tamaño diferente la celda activa de nuestra hoja de cálculo, pero con la condición de volver a una situación normal una vez la abandonemos al movernos a otra celda:

...Al seleccionar una celda (celda activa), que esta cambie de color y aumente el alto de la celda, pero sólo eso, debe mantener todo lo demás sin modificación alguna y al seleccionar otra celda, la anterior vuelva a su estado normal...


Para realizar esta acción notaremos un nuevo evento:
SelectionChange
el cual ejecutará la macro cuando cambie la selección de celda en nuestra hoja de cálculo.
El código siguiente se incluirá dentro del editor de VBA (Alt+F11) dentro de cada Hoja(no en un módulo):

'código VBA que cambia el color y tamaño de la celda activa.
Private sub worksheet_selectionchange(ByVal target As Range)
Static celdaanterior As Range
If Not celdaanterior Is Nothing Then
celdaanterior.Interior.ColorIndex = xlColorIndexNone
Rows(celdaanterior.Row).UseStandardHeight = True
End If

ActiveCell.Interior.Color = 65535
Rows(ActiveCell.Row).RowHeight = 27
Set celdaanterior = Target.EntireRow
End sub


Con el código desarrollado logramos que cambie el color de fondo y altura de la celda activa (amarillo y altura 27), además al cambiar a otra celda esta última vuelve a su estado normal; respetando cualquier formato anterior.

30 comentarios:

  1. Muy buena solución a un problema que estaba intentando resolver. Muchas gracias.
    Quisiera además saber si es posible asignar una imagen o "picture" a una celde de tal modo que al cambiar el valor de la celda cambie la imagen ???

    ResponderEliminar
  2. Hola,
    por supuesto es posible, sólo necesitas tener definidos los parámetros del cambio, es decir, de acuerdo a qué valores qué imágenes deseas.

    En primer lugar cópiate las imágenes que desees en la hoja donde quieras que se vean. Después selecciona cada uno de las imagenes, fijándote en la parte izquierda de la barra de fórmula el nombre asignado a cada imagen.

    Suponemos dos imagenes ('imagen 1' e 'imagen 2'); el código vba sería:
    Private Sub Worksheet_Change(ByVal Target As Range)
    Valor = Range("A1").Value
    If Valor < 100 Then
    ActiveSheet.Pictures("Picture 3").Visible = True
    ActiveSheet.Pictures("Picture 4").Visible = False
    Else
    ActiveSheet.Pictures("Picture 3").Visible = False
    ActiveSheet.Pictures("Picture 4").Visible = True
    End If
    End Sub

    Importante copiar el código en el editor de VBA en la Hoja de trabajo en cuestión.
    Slds

    ResponderEliminar
  3. en que lugar de visual inserto el codigooo. ??? graciass por la ayuda!!!

    ResponderEliminar
  4. Hola,
    si te refieres al código del post se incluye dentro del Editor de VBA en la Hoja te interese se ejecute tal macro (no en un Módulo).
    De igual forma el código del comentario...
    depende de dónde y cómo quieres que se ejecute...
    Espero haberte aclarado algo.
    Slds

    ResponderEliminar
  5. Hola
    Se que esto es del año pasado, pero creo que puedo aportar una solución más que elegante (no tengo awela :-)

    Vamos a asignar una imagen a partir de una que esta en el disco duro

    Dim picPicture As IPictureDisp
    Dim PathActual As String

    PathActual = ThisWorkbook.Path

    Insertamos un contenedor de imagenes en la hoja y le llamamos ImgContenedor (en propiedades, name), y le damos valor a picpicture

    Set picPicture = stdole.StdFunctions.LoadPicture(Trim(Trim(PathActual) & trim("NombreDeLaImagen.jpg"))

    Picpicture ya se puede utilizar como imagen en el contenedor, así:

    ActiveWorkbook.Sheets("Hoja1").ImgContenedor.Picture = picPicture

    Comenta, plis

    Saludos

    Javier
    MaGo0

    ResponderEliminar
    Respuestas
    1. Hola Javier,
      supongo que estás mejorando el comentario de más arriba y no el código del post...
      Pues está bien, pero al fin y al cabo también acabas teniendo que añadir 'a mano' en la hoja de cálculo ese contenedor (ImgContenedor)... En todo caso, la idea me parece, efectivamente más directa; ya que las imagenes las trae de fuera...

      Por cierto, habría que definir que es:
      stdole
      stdfunctions

      Un cordial saludo, y gracias por la aportación.

      Eliminar
  6. Hola de nuevo

    Bueno, tambien sería posible insertar ese contenedor mediante código

    Dim CuadroImagen As Object

    Set CuadroImagen= ActiveSheet.OLEObjects.Add(ClassType:="Forms.Image.1", _
    Link:=(true o false), _
    DisplayAsIcon:=(True o false), _
    Left:=Valor,
    Top:=Valor,
    Width:=Valor,
    Height:=Valor)

    Ahora le damos un nombre

    CuadroImagen.name="ImgContenedor"

    Y ya podemos trabajar con ella, usando el código de mi post anterior.

    Con respecto a stdole, mirar aquí

    http://fossies.org/dox/VirtualBox-4.1.8/namespacestdole.html

    COn este código se podría perfectamente hacer una XLA para usarlo en una hoja "sin nada", o sea partir de una hoja en blanco.

    Saludetes.

    ResponderEliminar
    Respuestas
    1. Gracias por la aclaración, y por la dirección donde obtener ese complemento.
      Slds

      Eliminar
  7. Hola, no se si este es el foro adecuado, si no lo es, disculpas de antemano:

    ¿Es posible proteger libro, hoja y código sin que le pasen los lammers por encima (que no hackers, contra esos no hay nada :P)?

    ResponderEliminar
    Respuestas
    1. Hola Javier...
      por desgracia, por mucha protección que demos a nuestros libros, hojas o VBA, siempre existirá un código que lo descubra.
      Yo al menos he visto por la web diferentes formas de hacerlo.
      Slds

      Eliminar
  8. Gracias
    Por cierto:
    ¡¡¡EXCELENTE BLOG!!!
    :)
    uN ABRAZO

    ResponderEliminar
  9. estoy usando el codigo de la celda activa funciona bien. pero tengo celdas de colores y al salirme de la celda me la vuelve blanca como puedo manterner el color original de la celda.

    ResponderEliminar
    Respuestas
    1. Hola, buenos días!!
      Espero te encuentres bien.

      Si deseas mantener el color original de la celda, deberás generar una variable que identifique el color de la celda seleccionada, para antes de salir del procedimiento volver a colorear el fondo asignándole la variable color original.

      Espero te haya orientado
      Un cordial saludo

      Eliminar
  10. Sip ya se esa parte. Lo que quiero es el codigo como seria cual es la sintaxis o comando que se usaria? en base a este codigo

    Private sub worksheet_selectionchange(ByVal target As Range)
    Static celdaanterior As Range
    If Not celdaanterior Is Nothing Then
    celdaanterior.Interior.ColorIndex = xlColorIndexNone
    Rows(celdaanterior.Row).UseStandardHeight = True
    End If
    ActiveCell.Interior.Color = 65535
    Rows(ActiveCell.Row).RowHeight = 27
    Set celdaanterior = Target.EntireRow
    End sub

    ResponderEliminar
    Respuestas
    1. Hola de nuevo, espero sigas bien.
      Quizá deberías leer antes las Normas de uso del blog.
      http://excelforo.blogspot.com.es/p/normas-de-uso.html
      Gracias y un saludo

      Eliminar
  11. gracias compañero estuvo bien la solucion

    ResponderEliminar
  12. Dónde puedo colocar una duda sobre una macro que detecta el color de la celda,
    tengo una duda ya que si pinto el fondo de color una condicion (usando el formato condicional) y despues mediante una macro trato de detectar el color, detecta la celda como NO PINTADA, como puedo solucionar esto?

    ResponderEliminar
    Respuestas
    1. Hola, que tal estás?
      espero te encuentres bien.
      Ten presente que el formato condicional no es un formato al uso, y por tanto no responde a las mismas propiedades que una celda 'pintada' normal.
      Lo que puedes conseguir saber es cuál es el color de fondo de la celda asignada en el formato condicional, pero no el que muestra en el momento actual.
      Por ejemplo, imagina la celda A2 con formato condicional y un color de fondo configurado, con
      Range("A2").FormatConditions(1).interior.colorindex
      obtendrías ese valor/color (repito no el mostrado).
      Siempre salvo mejor opinión.
      Slds cordiales

      Eliminar
  13. Hola,
    me parece muy elegante el código utilizado en esta función.
    Me pregunto si me puedes ayudar, lo que estoy intentando es algo parecido a lo que nos enseñaste, me explico:

    Lo que busco es que si la celda activa es la celda A13 se cambie el color, (verde por ejemplo), de la celda A9 y si ahora la celda activa es la celda A14, se cambie el color de la celda B9 y la celda A9 no tenga ningún color, así sucesivamente hasta la celda A24 y L9, pero mientras no se seleccione ninguna de este rango de celdas (A13 a A24), no pase nada, que el rango A9 a L9 no tenga color alguno.

    Espero me puedas ayudar y sobre todo haber explicado bien el proceso que necesito, de antemano agradezco mucho el apoyo que nos brindas.
    Saludos.

    ResponderEliminar
    Respuestas
    1. Hola,
      lo primero que deberías hacer es restringir con el método Intersect http://excelforo.blogspot.com.es/2011/06/vba-el-metodo-intersect.html
      El código para el color sería (a incluir igualmente en la Hoja dentro del editor de VB):
      Private Sub worksheet_selectionchange(ByVal target As Range)
      Static celdaanterior As Range

      If Not celdaanterior Is Nothing Then
      celdaanterior.Interior.ColorIndex = xlColorIndexNone
      Rows(celdaanterior.Row).UseStandardHeight = True
      End If
      Set celda = Cells(9, ActiveCell.Row - 12)

      celda.Interior.Color = 65535
      Rows(celda.Row).RowHeight = 27
      Set celdaanterior = celda.EntireRow
      End Sub

      Espero te sirva.
      Slds

      Eliminar
  14. Muchas Gracias por tu apoyo, lo reviso y te comento como me fue.

    Saludos.

    ResponderEliminar
    Respuestas
    1. ok,
      recuerda incluir en el procedimiento, para controlar el rango de actuación, el condicional con INTERSECT
      Sdls

      Eliminar
    2. Excelente

      Muchas gracias por tu ayuda y apoyo, ya complemente los dos códigos y me quedo como lo requiero.

      Nuevamente agradezco tu ayuda.

      Esperando que tu foro siga ayudandonos por mucho tiempo.

      Saludos

      Eliminar
    3. Perfecto!
      muchas gracias y un cordial saludo

      Eliminar
  15. Muy buen aporte, voy avanzando en lo que busco, pero tengo un problema.
    El código funciona bien, pero después no vuelve al color ni altura original.
    Otro usuario pregunto lo mismo más arriba.

    ResponderEliminar
    Respuestas
    1. Hola Juan,
      correcto, ya lo preguntaron, y la respuesta no puede ser otra:
      Si deseas mantener el color original de la celda, deberás generar una variable que identifique el color de la celda seleccionada, para antes de salir del procedimiento volver a colorear el fondo asignándole la variable color original.

      Es decir, al comienzo de la macro, identifica mediante variables qué propiedades.

      O bien optar por este otro método algo diferente, que se aprovecha de los formatos condicionales:
      Private Sub Worksheet_SelectionChange(ByVal Target As Range)
      Dim ColorCelda As Long

      On Error Resume Next
      ColorCelda = Target.Interior.ColorIndex
      MsgBox ColorCelda
      If ColorCelda < 0 Then
      ColorCelda = 36
      End If

      Cells.FormatConditions.Delete
      With Target
      .FormatConditions.Add Type:=2, Formula1:="VERDADERO"
      .FormatConditions(1).Interior.ColorIndex = ColorCelda
      End With

      End Sub

      OJO!! por que elimina todos los formatos condicionales de la hoja!!!
      Saludos

      Eliminar
  16. Muchas gracias, no sabía como crear la variable. Al final me quedo así :
    Private Sub Worksheet_SelectionChange(ByVal Target As Range)

    Dim ColorCelda As Long
    On Error Resume Next
    ColorCelda = Target.Interior.ColorIndex
    If ActiveCell.Value < 0 Then
    With Selection.Font
    .Size = 12
    .Color = -16776961
    .Bold = True
    End With
    ElseIf ColorCelda < 0 Then
    ColorCelda = 36
    End If
    Cells.FormatConditions.Delete
    With Target
    .FormatConditions.Add Type:=2, Formula1:="VERDADERO"
    .FormatConditions(1).Interior.ColorIndex = ColorCelda
    End With
    End Sub
    Le agregue una condición más que es lo único que necesito =).
    Muchas gracias
    Bueno, tampoco se puede ocupar deshacer (ctrl+z), me es de mucha ayuda, ya que es una planilla con más de 1millon de datos. 3mil filas y 400columnas aprox y muchas veces me pierdo.
    Muchas gracias de nuevo =)

    ResponderEliminar
    Respuestas
    1. Hola Juan,
      me alegro te sirviera alguna de las soluciones....
      Un cordial saludo!!

      Eliminar
  17. hola, me re sirvio tu solucion.
    lo que te queria es consultar, si hay posibilidad de que la celda activa no cambie de color, pero si que cambie el contro de la celda activa. Gracias

    ResponderEliminar
    Respuestas
    1. Hola!
      perdóname, pero no comprende ...
      Claro está basta eliminar las líneas de código que tocan el color, pero no entiendo a qué te refieres a que 'cambie el control de la celda activa'
      :(
      Slds

      Eliminar