Мне нужна была эта функция, и мне не понравились все вышеперечисленные решения после большинства попыток, так как они либо
- Медленно
- Имеют сложные последствия, такие как использование application.undo.
- Не снимать, если они не были выбраны
- Не фиксирует значения, если они не были изменены ранее
- Слишком сложный
Ну, я очень много думал об этом, и я закончил решение для полной истории UNDO, REDO.
Чтобы уловить старое значение, это на самом деле очень просто и очень быстро.
Мое решение - захватить все значения, как только пользователь откроет лист, откроет переменную, и он обновляется после каждого изменения. эта переменная будет использоваться для проверки старого значения ячейки. В вышеупомянутых решениях все они используются для цикла. На самом деле есть способ проще.
Для захвата всех значений я использовал эту простую команду
SheetStore = sh.UsedRange.Formula
Да, просто, Excel на самом деле вернет массив, если диапазон состоит из нескольких ячеек, поэтому нам не нужно использовать команду FOR EACH, и она очень быстрая
Следующий подпункт является полным кодом, который должен вызываться в Workbook_SheetActivate. Еще одна подпрограмма должна быть создана, чтобы зафиксировать изменения. Например, у меня есть подпрограмма "catchChanges", которая работает на Workbook_SheetChange. Он запишет изменения и сохранит их на другом листе истории изменений. затем запускает UpdateCache для обновления кеша новыми значениями
' should be added at the top of the module
Private SheetStore() As Variant
Private SheetStoreName As String ' I use this variable to make sure that the changes I captures are in the same active sheet to prevent overwrite
Sub UpdateCache(sh As Object)
If sh.Name = ActiveSheet.Name Then ' update values only if the changed values are in the activesheet
SheetStoreName = sh.Name
ReDim SheetStore(1 To sh.UsedRange.Rows.count, 1 To sh.UsedRange.Columns.count) ' update the dimension of the array to match used range
SheetStore = sh.UsedRange.Formula
End If
End Sub
теперь получить старое значение очень просто, так как массив имеет одинаковый адрес ячеек
примеров, если нам нужна ячейка D12, мы можем использовать следующее
SheetStore(row_number,column_number)
'example
return = SheetStore(12,4)
' or the following showing how I used it.
set cell = activecell ' the cell that we want to find the old value for
newValue = cell.value ' you can ignore this line, it is just a demonstration
oldValue = SheetStore(cell.Row, cell.Column)
это фрагмент, объясняющий метод, надеюсь, всем понравится