Hi Andreas,
Indeed, large selections will lead to performance issues.
Events driven codes should always be limited to a specific range, using the Intersect method, or limited to the UsedRange.
Option Explicit
Dim PrevValue As Object, Cell As Range
Const Rng As String = "A1:Z100"
Private Sub Worksheet_Change(ByVal Target As Range)
If PrevValue is Nothing then exit sub
If Not Intersect(Target, Me.Range(Rng)) Is Nothing Then
For Each Cell In Intersect(Target, Me.Range(Rng))
If PrevValue(Cell.Address) <> Cell.Value Then
Sheets("log").Cells(65000, 1).End(xlUp).Offset(1, 0).Value = _
Application.UserName & " changed cell " & " " & Me.Name & " " & Cell.Address _
& " from " & PrevValue(Cell.Address) & " to " & Cell.Value & " at: " & Format(Time, "hh:mm:ss") & " on: " & Format(Date, "dd/mm/yy")
End If
Next
End If
End Sub
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
If Not Intersect(Target, Me.Range(Rng)) Is Nothing Then
Set PrevValue = CreateObject("Scripting.Dictionary")
For Each Cell In Intersect(Target, Me.Range(Rng))
PrevValue.Add Key:=Cell.Address, Item:=Cell.Value
Next Cell
End If
Thank you for your observations :)
Each method has advantages and disadvantages, as you already know, there are many ways to solve a problem, but a user should decide what is best for him, in his scenario. For example, if user choose to exit when Target.Cells.Count>1, this will prevent him
from capturing mass changes like Ctrl+Enter in a selected range, or Ctrl+V over a range of cells. So Alan has to know all implications of not allowing the code to run when Target.Cells.Count>1 and he wants just to avoid the error and ignore mass changes.
Personally, I consider that if he needs to track the changes, then the code must run, no matter if the change is for 1 cell or multiple cells, otherwise the log will be incomplete.