Обычно при обновлении ячейки новым содержимым предыдущее значение будет закрыто, если не отменить операцию в Excel. Однако, если вы хотите сохранить предыдущее значение для сравнения с обновленным, сохранение предыдущего значения ячейки в другую ячейку или в комментарий к ячейке будет хорошим выбором. Метод, описанный в этой статье, поможет вам в этом.
Сохранить предыдущее значение ячейки с кодом VBA в Excel
Сохранить предыдущее значение ячейки с кодом VBA в Excel
Предположим, у вас есть таблица, как показано на скриншоте ниже. Если какая-либо ячейка в столбце C изменилась, вы хотите сохранить ее предыдущее значение в соответствующей ячейке столбца G или автоматически сохранить в комментарии. Для этого сделайте следующее.
1. На рабочем листе содержится значение, которое вы сохраните при обновлении, щелкните правой кнопкой мыши вкладку листа и выберите Просмотреть код из контекстного меню. Смотрите скриншот:
2. В дебюте Microsoft Visual Basic для приложений Скопируйте приведенный ниже код VBA в окно кода.
Следующий код VBA помогает сохранить предыдущее значение ячейки указанного столбца в другой столбец.
Код VBA: сохранить предыдущее значение ячейки в другую ячейку столбца
Dim xRg As Range
Dim xChangeRg As Range
Dim xDependRg As Range
Dim xDic As New Dictionary
Private Sub Worksheet_Change(ByVal Target As Range)
Dim I As Long
Dim xCell As Range
Dim xDCell As Range
Dim xHeader As String
Dim xCommText As String
On Error Resume Next
Application.ScreenUpdating = False
Application.EnableEvents = False
xHeader = "Previous value :"
x = xDic.Keys
For I = 0 To UBound(xDic.Keys)
Set xCell = Range(xDic.Keys(I))
Set xDCell = Cells(xCell.Row, 7)
xDCell.Value = ""
xDCell.Value = xDic.Items(I)
Next
Application.EnableEvents = True
Application.ScreenUpdating = True
End Sub
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
Dim I, J As Long
Dim xRgArea As Range
On Error GoTo Label1
If Target.Count > 1 Then Exit Sub
Application.EnableEvents = False
Set xDependRg = Target.Dependents
If xDependRg Is Nothing Then GoTo Label1
If Not xDependRg Is Nothing Then
Set xDependRg = Intersect(xDependRg, Range("C:C"))
End If
Label1:
Set xRg = Intersect(Target, Range("C:C"))
If (Not xRg Is Nothing) And (Not xDependRg Is Nothing) Then
Set xChangeRg = Union(xRg, xDependRg)
ElseIf (xRg Is Nothing) And (Not xDependRg Is Nothing) Then
Set xChangeRg = xDependRg
ElseIf (Not xRg Is Nothing) And (xDependRg Is Nothing) Then
Set xChangeRg = xRg
Else
Application.EnableEvents = True
Exit Sub
End If
xDic.RemoveAll
For I = 1 To xChangeRg.Areas.Count
Set xRgArea = xChangeRg.Areas(I)
For J = 1 To xRgArea.Count
xDic.Add xRgArea(J).Address, xRgArea(J).Formula
Next
Next
Set xChangeRg = Nothing
Set xRg = Nothing
Set xDependRg = Nothing
Application.EnableEvents = True
End Sub
Чтобы сохранить предыдущее значение ячейки в комментарии, примените приведенный ниже код VBA.
Код VBA: сохранить предыдущее значение ячейки в комментарии
Dim xRg As Range
Dim xChangeRg As Range
Dim xDependRg As Range
Dim xDic As New Dictionary
Private Sub Worksheet_Change(ByVal Target As Range)
Dim I As Long
Dim xCell As Range
Dim xHeader As String
Dim xCommText As String
On Error Resume Next
Application.ScreenUpdating = False
Application.EnableEvents = False
xHeader = "Previous value :"
For I = 0 To UBound(xDic.Keys)
Set xCell = Range(xDic.Keys(I))
If Not xCell.Comment Is Nothing Then xCell.Comment.Delete
With xCell
.AddComment
.Comment.Visible = False
.Comment.Text xHeader & vbCrLf & xDic.Items(I)
End With
Next
Application.EnableEvents = True
Application.ScreenUpdating = True
End Sub
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
Dim I, J As Long
Dim xRgArea As Range
On Error GoTo Label1
If Target.Count > 1 Then Exit Sub
Application.EnableEvents = False
Set xDependRg = Target.Dependents
If xDependRg Is Nothing Then GoTo Label1
If Not xDependRg Is Nothing Then
Set xDependRg = Intersect(xDependRg, Range("C:C"))
End If
Label1:
Set xRg = Intersect(Target, Range("C:C"))
If (Not xRg Is Nothing) And (Not xDependRg Is Nothing) Then
Set xChangeRg = Union(xRg, xDependRg)
ElseIf (xRg Is Nothing) And (Not xDependRg Is Nothing) Then
Set xChangeRg = xDependRg
ElseIf (Not xRg Is Nothing) And (xDependRg Is Nothing) Then
Set xChangeRg = xRg
Else
Application.EnableEvents = True
Exit Sub
End If
xDic.RemoveAll
For I = 1 To xChangeRg.Areas.Count
Set xRgArea = xChangeRg.Areas(I)
For J = 1 To xRgArea.Count
xDic.Add xRgArea(J).Address, xRgArea(J).Text
Next
Next
Set xChangeRg = Nothing
Set xRg = Nothing
Set xDependRg = Nothing
Application.EnableEvents = True
End Sub
Внимание: В коде цифра 7 указывает столбец G, в который вы сохраните предыдущую ячейку, а C: C — столбец, в котором вы сохраните предыдущее значение ячейки. Пожалуйста, измените их в соответствии с вашими потребностями.
3. Нажмите Tools
> Рекомендации для открытия Ссылки — VBAProject диалоговое окно, проверьте Среда выполнения сценариев Microsoft поле и, наконец, щелкните OK кнопка. Смотрите скриншот:
4. нажмите другой + Q ключи, чтобы закрыть Microsoft Visual Basic для приложений окно.
С этого момента, когда значение ячейки в столбце C обновляется, предыдущее значение ячейки будет сохранено в соответствующие ячейки в столбце G или будет сохранено в комментариях, как показано на скриншотах ниже.
Сохраните предыдущие значения ячеек в других ячейках:
Сохраните предыдущие значения ячеек в комментариях:
Лучшие инструменты для работы в офисе
Kutools for Excel Решит большинство ваших проблем и повысит вашу производительность на 80%
- Снова использовать: Быстро вставить сложные формулы, диаграммы и все, что вы использовали раньше; Зашифровать ячейки с паролем; Создать список рассылки и отправлять электронные письма …
- Бар Супер Формулы (легко редактировать несколько строк текста и формул); Макет для чтения (легко читать и редактировать большое количество ячеек); Вставить в отфильтрованный диапазон…
- Объединить ячейки / строки / столбцы без потери данных; Разделить содержимое ячеек; Объединить повторяющиеся строки / столбцы… Предотвращение дублирования ячеек; Сравнить диапазоны…
- Выберите Дубликат или Уникальный Ряды; Выбрать пустые строки (все ячейки пустые); Супер находка и нечеткая находка во многих рабочих тетрадях; Случайный выбор …
- Точная копия Несколько ячеек без изменения ссылки на формулу; Автоматическое создание ссылок на несколько листов; Вставить пули, Флажки и многое другое …
- Извлечь текст, Добавить текст, Удалить по позиции, Удалить пробел; Создание и печать промежуточных итогов по страницам; Преобразование содержимого ячеек в комментарии…
- Суперфильтр (сохранять и применять схемы фильтров к другим листам); Расширенная сортировка по месяцам / неделям / дням, периодичности и др .; Специальный фильтр жирным, курсивом …
- Комбинируйте книги и рабочие листы; Объединить таблицы на основе ключевых столбцов; Разделить данные на несколько листов; Пакетное преобразование xls, xlsx и PDF…
- Более 300 мощных функций. Поддерживает Office/Excel 2007-2021 и 365. Поддерживает все языки. Простое развертывание на вашем предприятии или в организации. Полнофункциональная 30-дневная бесплатная пробная версия. 60-дневная гарантия возврата денег.
Вкладка Office: интерфейс с вкладками в Office и упрощение работы
- Включение редактирования и чтения с вкладками в Word, Excel, PowerPoint, Издатель, доступ, Visio и проект.
- Открывайте и создавайте несколько документов на новых вкладках одного окна, а не в новых окнах.
- Повышает вашу продуктивность на 50% и сокращает количество щелчков мышью на сотни каждый день!
Комментарии (20)
Оценок пока нет. Оцените первым!
@Shelbie1288
Here are two possible solutions that you could use in brief. The first is for the current cell. Even if several cells are selected, only the current cell is converted:
Sub RngFormelZuWert ()
Dim c As Range
For Each c In Selection
c.Value = c.Value
Next c
End Sub
Yes, you can also do without the word Value, because in this case it is the default property. But better safe than sorry, and this is how it will work 10 years from now.
The second possibility would be that all cells in a marked area should be «treated» in this way. Then this code leads to the goal:
Sub RngFormelZuWert ()
Dim c As Range
For Each c In Selection
c.Value = c.Value
Next c
End Sub
You can see that this is hardly more code than in the first example.
Is for everyone who would like to have it short and sweet:
Sub Sel2Val ()
Selection.Value = Selection.Value
End Sub
I hope that I was able to help you further, or to provide a solution.
I would be happy to know if I could help.
Nikolino
I know I don’t know anything (Socrates)
* Kindly Mark and Vote this reply if it helps please, as it will be beneficial to more Community members reading here.
Добрый день, Ув. Форумчане! Прошу подсказать решение следующей задачи: Прикрепленные файлы
|
|
webley Пользователь Сообщений: 1995 |
#2 03.02.2022 11:36:08 Добрый день. А если без Worksheet_SelectionChange, вот так?
|
||
ANDREY Пользователь Сообщений: 24 |
|
Спасибо за вариант, но при первом запуске это работать не будет, т.к. переменная СтароеЗначение изначально будет пустой. |
|
webley Пользователь Сообщений: 1995 |
ну тогда можно совместить — первоначальное значение присваивать, например, через Worksheet_SelectionChange (хотя можно при активации листа/открытии книги), а изменение уже отслеживать «по факту» в процедуре Worksheet_Change |
ANDREY Пользователь Сообщений: 24 |
#6 03.02.2022 12:26:05
Данная переменная перестает быть пустой при выделении или активации ячейки. Если в этой ячейке отсутствует значение, то значит предыдущее значение «». И это можно обработать. |
||
vikttur Пользователь Сообщений: 47199 |
#7 03.02.2022 12:26:26 В Worksheet_Change
|
||
Alexey0185 Пользователь Сообщений: 133 |
#8 03.02.2022 12:28:01 ANDREY, в том и проблема, что через Worksheet_SelectionChange значение присваивается, если ячейка до этого не была активной. А если она в данный момент активна, то Worksheet_SelectionChange не срабатывает.
Благодарю!!! Работает! |
||
Alexey0185 Пользователь Сообщений: 133 |
#9 03.02.2022 12:33:13
Благодарю!!! Работает! ANDREY, Изменено: vikttur — 03.02.2022 12:41:53 |
||
БМВ Модератор Сообщений: 21383 Excel 2013, 2016 |
#10 03.02.2022 12:41:41 Alexey0185, смотрите что написал vikttur.
или можно с трудом натянуть на неразрывный диапазон, но сейчас если скопировать что-то в A1:b1, то сломается. ну и тут не простой но вариант По вопросам из тем форума, личку не читаю. |
||
vikttur Пользователь Сообщений: 47199 |
#11 03.02.2022 12:45:14 Не схитрил, а предложил
И про application забыл… |
||
Alexey0185 Пользователь Сообщений: 133 |
#12 03.02.2022 12:58:40 БМВ
, благодарю!
Про application я и сам догуглил. Направление задали верное — это главное. |
||
БМВ Модератор Сообщений: 21383 Excel 2013, 2016 |
#13 03.02.2022 13:08:03 Уппс, а я вот никогда не пользовал undo undo и думал что по стеку идет в одном направлении, а оно именно одно действие отменяет, при этом сама отмена становится последним…
По вопросам из тем форума, личку не читаю. |
||
_Igor_61 Пользователь Сообщений: 3007 |
Михаил, СПАСИБО!!! . Изменено: _Igor_61 — 03.02.2022 15:44:02 |
Достаточно давно я описывал данный подход в статье: Выделение сделанных изменений только возвращал я свойство .Formula, т.к. это чуть более правильно в случаях, если изменения вносились в ячейку с формулой. Ну и еще парочка дополнений там есть, вроде возврата выделенных ячеек в исходное положение, т.к. после Undo выделенная область тоже может смениться. Даже самый простой вопрос можно превратить в огромную проблему. Достаточно не уметь формулировать вопросы… |
|
sokol92 Пользователь Сообщений: 4445 |
Здравствуйте, коллеги! Изменено: sokol92 — 03.02.2022 17:55:42 |
sokol92, что-то у меня не получилось повторить. Сделал четко по озвученному алгоритму. Ни сообщения, ни ошибку не получил. Что делаю не так? Изменено: Дмитрий(The_Prist) Щербаков — 03.02.2022 17:59:36 Даже самый простой вопрос можно превратить в огромную проблему. Достаточно не уметь формулировать вопросы… |
|
sokol92 Пользователь Сообщений: 4445 |
Дмитрий, не знаю — я раз 20 проверял. Важно нажимать именно Backspace, а не Del. Изменено: sokol92 — 03.02.2022 18:11:29 |
Дмитрий(The_Prist) Щербаков Пользователь Сообщений: 14182 Профессиональная разработка приложений для MS Office |
#19 03.02.2022 18:16:56
вот теперь понятно. Дело-то по сути в проверке данных и не Undo проблему создает, а проверка данных, т.к. Und-ить нечего
Но можно и при любой ошибке выход делать Даже самый простой вопрос можно превратить в огромную проблему. Достаточно не уметь формулировать вопросы… |
||||
sokol92 Пользователь Сообщений: 4445 |
#20 03.02.2022 18:22:34
Да. Там событие изменения ячейки A1 вызывается дважды. P.S. Ошибка исчезновения имени при цитировании не исправлена. Все время забываю нажимать на «BB code». Изменено: sokol92 — 03.02.2022 18:25:54 Владимир |
||
БМВ Модератор Сообщений: 21383 Excel 2013, 2016 |
#21 03.02.2022 19:48:01
там тоже On Error Resume Next Спасибо за тест кейс. ДА все верно, нужно обрабатывать ошибки подобные. Я тут на досуге посмотрел вариант для подобного контроля в диапазоне на случай копирования диапазона. ну собственно идея то примитивная, но приходится сохранять адреса, ячеек измененных и их значение в массив а потом по нему уже все тоже самое. По вопросам из тем форума, личку не читаю. |
||
автосохраниение предыдущих значений |
||||||||
Ответить |
||||||||
Ответить |
||||||||
Ответить |
||||||||
Ответить |
||||||||
Ответить |
||||||||
Ответить |
||||||||
Ответить |
||||||||
Ответить |
||||||||
Ответить |
||||||||
Ответить |
||||||||
Ответить |
||||||||
Ответить |
||||||||
Ответить |
||||||||
Ответить |
||||||||
Ответить |
||||||||
Ответить |
||||||||
Ответить |
||||||||
Ответить |
||||||||
Ответить |
||||||||
Ответить |
@Shelbie1288
Here are two possible solutions that you could use in brief. The first is for the current cell. Even if several cells are selected, only the current cell is converted:
Sub RngFormelZuWert ()
Dim c As Range
For Each c In Selection
c.Value = c.Value
Next c
End Sub
Yes, you can also do without the word Value, because in this case it is the default property. But better safe than sorry, and this is how it will work 10 years from now.
The second possibility would be that all cells in a marked area should be «treated» in this way. Then this code leads to the goal:
Sub RngFormelZuWert ()
Dim c As Range
For Each c In Selection
c.Value = c.Value
Next c
End Sub
You can see that this is hardly more code than in the first example.
Is for everyone who would like to have it short and sweet:
Sub Sel2Val ()
Selection.Value = Selection.Value
End Sub
I hope that I was able to help you further, or to provide a solution.
I would be happy to know if I could help.
Nikolino
I know I don’t know anything (Socrates)
* Kindly Mark and Vote this reply if it helps please, as it will be beneficial to more Community members reading here.