miércoles, octubre 24, 2012

Registrar fecha y hora de una entrada en Excel con eventos

En la nota anterior vimos como registrar la fecha y hora de una entrada (timestamp) usando fórmulas.

Por supuesto puede hacerse también con macros, más precisamente, programando un evento.

El código del evento, que ponemos en el módulo de la hoja correspondiente, es el siguiente:

Private Sub Worksheet_Change(ByVal Target As Range)
    Dim rngColumnaNombre As Range
   
    Set rngColumnaNombre = Range("A:A")
   
    If Union(Target, rngColumnaNombre).Address = rngColumnaNombre.Address Then
        Select Case Len(Target)
            Case Is > 0
                Target.Offset(0, 1) = Now
            Case Else
                Target.Offset(0, 1).ClearContents
        End Select
    End If
      
End Sub


En nuestro ejemplo la columna A contiene los nombres y la columna B el registro de la fecha. Si borramos un nombre, también la fecha es eliminada.




El código evalúa la celda activa cuando se produce un cambio en la hoja; si la celda activa está en la columna A y no esta vacía, se registra la fecha y hora en la celda paralela de la columna B.

En este código definimos una variable de tipo rango

Set rngColumnaNombre = Range("TablaNombres").Columns(1)

La variable se refiere a la primera columna de la tabla “TablaNombres”


Esto nos permite crear una rango dinámico de manera que valores introducidos fuera de la tabla no disparan el evento.

Existen, por supuesto, otras formas de crear rangos dinámicos en el código.

1 – crear un nombre que se refiera al rango dinámico usando una fórmula con las funciones DESREF o INDICE; por ejemplo

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



El código es

Private Sub Worksheet_Change(ByVal Target As Range)
   
    If Union(Target, Range("TablaNombres")).Address = Range("TablaNombres").Address Then
        Select Case Len(Target)
            Case Is > 0
                Target.Offset(0, 1) = Now
            Case Else
                Target.Offset(0, 1).ClearContents
        End Select
    End If
      
End Sub


2 – definir el rango en el código

Private Sub Worksheet_Change(ByVal Target As Range)
    Dim TablaNombres As Range
   
    Set TablaNombres = Range(Range("A2"), Cells(Range("A2").End(xlDown).Row + 1, 1))
    If Union(Target, TablaNombres).Address = TablaNombres.Address Then
        Select Case Len(Target)
            Case Is > 0
                Target.Offset(0, 1) = Now
            Case Else
                Target.Offset(0, 1).ClearContents
        End Select
    End If
      
End Sub

6 comentarios:

  1. Yo normalmente comparo la columna y la fila:

    With target
    If .column = 1 and .row > 1 then
    if .value ="" then
    .offset(0,1).clearcontents
    else
    .offset(0,1).value = now
    end if
    end if
    end With

    Claro que dependo que la estructura de la hoja no se altere.

    ResponderBorrar
  2. Hola Jorge, ante todo felicidades por tu excel-ente blog, me ha ayudado muchisimo.

    Tengo un problemilla con el evento Worksheet_FollowHyperlink, si lo uso con hipervinculos directos funciona perfecto, pero cuando lo intento con la función HIPERVINCULO no los reconoce. Necesito usar estos ultimos porque estan en una lista que se va ordenando en funcion de la variación de los datos y los hipervinculos directos se desordenan, se te ocurre algo?

    Muchisimas gracias por todo y sigue asi...

    ResponderBorrar
  3. Hola Juan, podrías usar el evento Worksheet_SelectionChange de esta manera:

    Private Sub Worksheet_SelectionChange(ByVal Target As Range)
    If Mid(Target.Formula, 2, 9) = "HYPERLINK" Then
    tu código
    End If
    End Sub

    ResponderBorrar
  4. Muchas gracias Jorge, va perfecto... como siempre

    ResponderBorrar
  5. Hola Jorge, Lo primero darte la enhorabuena por el blog, lo encontre hace unos dias y por lo que he visto esta muy bien, y ya me ha solucionado un par de problemillas. Ahora estoy intentando hacer algo parecido a lo que propones, pero estoy un poco trabado. Veras, tengo una hoja que hace una consulta via web para obtener el valor de una celda, lo que quiero lograr es que me detecte el cambio en el valor de la celda y que me guarde en una columna los distintos valores que va tomando esa celda. Dificil?, para mi un poco la verdad.
    Gracias.

    ResponderBorrar
  6. Carlos, no es tan difícil pero el marco de un comentario no da para una explicación. Te sugiero que te pongas en contacto conmigo por mail privado (instrucciones en el enlace Ayuda, en la parte superior de la plantilla).

    ResponderBorrar

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