Como registrar a data e a hora em que uma célula foi alterada

Uma pergunta muito comum é como registrar numa célula a data+hora em que outra célula foi alterada. A primeira solução que vem a mente é usar a função agora(). Acontece que essa função é reavaliada toda vez que QUALQUER célula for modificada posteriormente. O que precisamos é registrar a data+hora em que a célula foi alterada e nunca mais alterar essa data+hora. Para fazer isso vamos usar uma macro.

Eis a macro que faz o que queremos numa versão bem simples que pode ser baixada aqui.

Private Sub Worksheet_Change(ByVal Alvo As Range)
Dim limite_maximo As Integer
limite_maximo = 100 ‘ altere aqui para limitar a última linha
‘ faz nada se mais de uma célula modificada ou se deu delete
If Alvo.Cells.Count > 1 Or IsEmpty(Alvo) Then Exit Sub

If Alvo.Column = 1 And Alvo.Row >= 2 And Alvo.Row <= limite_maximo Then
‘ o if acima garante que a célula modificada está dentro a2:a100

‘ desliga captura do evento change
Application.EnableEvents = False
‘ muda a célula C da linha correspondente
Alvo.Offset(0, 2).Value = Time()
‘ religa a captura de eventos
Application.EnableEvents = True
End If

End Sub

Como funciona essa macro ?

Essa macro tem um nome especial chamada worksheet_change()
Ela é acionada sempre que qualquer célula for modificada manualmente. Ou seja, quando alguém modificar uma célula e teclar ENTER, essa macro será acionada. Ela não será acionada quando copiar/colar, ou quando  um cálculo mudar o valor de uma célula ou quando outra macro mudar o valor da célula. Ela só é acionada se a modificação for feita manualmente.

Além do nome especial, essa macro também é gravada num local especial. Clique-direito sobre o nome da aba que contém a planilha e acione a opção “Exibir código”. Nesse espaço cole a macro acima. Se colocar em outro lugar, a macro não será acionada automaticamente e não vai funcionar.

A sub worksheet_change() recebe como parâmetro a faixa que foi modificada. Observe que a sub recebe uma faixa e não uma simples célula. Isso significa que é possível em alguns casos editar mais de uma célula ao mesmo tempo.

Resumindo até aqui, a sub worksheet_change é acionada quando alguém edita uma célula (ou faixa de células), tem que ser gravada na parte “exibir código” da planilha e passa como parâmetro a faixa que foi modificada.

Agora vamos ao que a macro faz.

A primeira coisa que a macro faz é criar uma variável que definirá quais células serão monitoradas. Esse limite foi definido simplesmente pelo número da linha e pelo número da coluna. No nosso caso, o limite de número de linha será 100. Isso significa que qualquer célula de linha <= (menor ou igual) a 100 será monitorada. Acima desse limite a macro não fará coisa alguma. Além desse limite superior de linha, existe um limite inferior de linha que está fixo em 2 no 2º IF.

Depois de definida a variável que conterá o limite superior, a próxima coisa que a macro faz é testar quantas células foram modificadas. Com a finalidade de simplificar a macro, testamos se mais de uma célula foi modificada contando quantos elementos tem a faixa passada como parâmetro. Se a faixa modificada tiver mais de uma célula ou se for vazia, saímos da macro sem fazer coisa alguma.

Agora vamos testar se a faixa modificada está dentro do limite escolhido. No caso vamos monitorar apenas o que for modificado na coluna A (coluna 1) a partir da 2ª linha até a linha definida pelo limite superior mencionado antes. Fazemos isso usando um IF em que testamos se a coluna (alvo.column) é 1 ( equivalente a coluna A) e se o número da linha (alvo.row) está dentro da faixa entre 2 e o limite. Se estiver, a brincadeira começa. Primeiro desligamos a captura de novas mudanças na planilha, para evitar que a sub worksheet_change() seja chamada enquanto ainda ela mesma ainda está sendo processada. Essa é uma medida de segurança e é efetivada com o comando application.enablevents = false que desliga a captura de eventos. agora vamos registrar na célula ao lado da célula modificada a data e hora. Isso é feito usando a propriedade OFFSET( 0 , 2 ) da célula modificada, que irá deslocar 0 linhas e 2 colunas para a direita, colocando nessa nova célula o valor da data e hora obtidos com a função vba TIME()

Agora é só religar a captura dos eventos e terminar a rotina.

Uma forma mais clara de detectar se a célula em que houve a mudança está na faixa que devemos monitorar é usar a função vba Intersect() assim

sub worksheet_change( byval alvo as range )
dim a_monitorar as range
set a_monitorar = range( “B2:B10” ) ‘ definimos aqui a faixa que queremos monitorar
if Intersect( alvo , a_monitorar ) Is Nothing Then exit sub ‘ se a interseção das faixas for nada, então está fora da faixa a monitorar, saímos da rotina

‘ colocamos aqui o código que queremos fazer
exit
end

Essa técnica de interceptação do evento de modificação da planilha pode ser usado para disparar macros que fazem outras coisas. Por exemplo, pode-se usar esse evento para chamar uma macro que coloca em ordem alfabética uma lista de pessoas numa faixa. Ou … atualizar um gráfico … ou levar os dados de uma parte da planilha para outra. Use a imaginação.

Anúncios