Версия для печати

Запись изменений на листе в примечания

Что умеет Excel

 

Сегодня от нечего делать решил написать эту статью. Может кому пригодится. Приведенный ниже код создает примечание в ячейке, если её значение было изменено. В примечание заноситься информация о том, что было занесено в ячейку и когда это было занесено. Если примечание в ячейке уже есть, то в имеющееся примечание допишется информация об изменениях.

Private Sub Worksheet_Change(ByVal Target As Range)
    Dim oComment As Comment
    On Error Resume Next
    Set oComment = Target.Comment
    If oComment Is Nothing Then
        Target.AddComment Target.Text & " " & Format(Now, "dd.mm.yy HH:MM")
    Else
        oComment.Text oComment.Text & Chr(10) & Target.Text & " " & Format(Now, "dd.mm.yy HH:MM")
    End If
End Sub
Private Sub Worksheet_Change(ByVal Target As Range)
    Dim oComment As Comment
    On Error Resume Next
    Set oComment = Target.Comment
    If oComment Is Nothing Then
        Target.AddComment Target.Text & " " & Format(Now, "dd.mm.yy HH:MM")
    Else
        oComment.Text oComment.Text & Chr(10) & Target.Text & " " & Format(Now, "dd.mm.yy HH:MM")
    End If
End Sub

Код необходимо поместить в модуль листа(щелкнуть правой кнопкой мыши по ярлычку листа — Исходный текст), изменения на котором необходимо отследить. Подробнее о модулях см.здесь.

Если хотите, чтобы в примечание заносилось предыдущее значение в ячейке и ограничить диапазон отслеживания изменений, то следует применить такой код:

Option Explicit
Public sValue As String
'заносим в переменную значение ячейки
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
    If Target.Count = 1 Then
        sValue = Target.Value
    End If
End Sub
Private Sub Worksheet_Change(ByVal Target As Range)
'отслеживаем изменения только в диапазоне "A1:B10"
    If Intersect(Target, Me.Range("A1:B10")) Is Nothing Then Exit Sub
    'сравниваем новое значение с прежним
    If CStr(Target.Value) <> sValue Then
        Dim oComment As Comment
        On Error Resume Next
        Set oComment = Target.Comment
        If oComment Is Nothing Then
            Target.AddComment Application.UserName & ":" & Chr(10) & sValue & " " & Format(Now, "dd.mm.yy HH:MM")
        Else
            oComment.Text oComment.Text & Chr(10) & Application.UserName & ":" & Chr(10) & sValue & " " & Format(Now, "dd.mm.yy HH:MM")
        End If
    End If
End Sub
Option Explicit
Public sValue As String
'заносим в переменную значение ячейки
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
    If Target.Count = 1 Then
        sValue = Target.Value
    End If
End Sub
Private Sub Worksheet_Change(ByVal Target As Range)
'отслеживаем изменения только в диапазоне "A1:B10"
    If Intersect(Target, Me.Range("A1:B10")) Is Nothing Then Exit Sub
    'сравниваем новое значение с прежним
    If CStr(Target.Value) <> sValue Then
        Dim oComment As Comment
        On Error Resume Next
        Set oComment = Target.Comment
        If oComment Is Nothing Then
            Target.AddComment Application.UserName & ":" & Chr(10) & sValue & " " & Format(Now, "dd.mm.yy HH:MM")
        Else
            oComment.Text oComment.Text & Chr(10) & Application.UserName & ":" & Chr(10) & sValue & " " & Format(Now, "dd.mm.yy HH:MM")
        End If
    End If
End Sub

Так же в данном коде перед значением добавляется имя пользователя, изменившего значение.
Хочу обратить внимание, что при попытке изменения нескольких ячеек сразу может возникнуть ошибка выполнения.

Скачать пример »

  Tips_Macro_ChangesInComment.xls (25,5 KiB, 1 163 скачиваний)

Так же см.:
Ведение журнала сделанных в книге изменений
Выделение сделанных изменений



Поддержать автора сайта
Поделиться ссылкой
  1. Сергей
    14 Ноябрь 2011 в 12:13 | #1

    Подскажите пожалуйста!

    1.Если в строчку скопировать значение, то все комментарии которые там были удаляются.
    2.Больше 3 коментариев не вмещается.
    Можно это все устранить!

  2. 14 Ноябрь 2011 в 21:53 | #2

    1. Вы явно копируете не только значения. Судя по результату Вы копируете ячейки целиком.
    2. Вмещается больше. Просто надо изменить размер примечания, т.к. не все вмещаются в размер примечения.

  3. Андрей
    18 Ноябрь 2011 в 00:52 | #3

    Мне кажется, что лучше бы в примечании отображалось значение ячейки, которое было до внесения изменений. Т.к. новое значение и так видно, достаточно только даты, когда оно было сделано.
    Можно ли дописать код, чтобы это действовало только на определённый диапазон ячеек листа, а не на весь лист. Сейчас получается, что весь лист со временем будет в примечаниях.
    Заранее благодарен,
    Андрей.

  4. 18 Ноябрь 2011 в 08:45 | #4

    Андрей, это конечно так. Но. Внесли одно изменение, затем другое. А старое значение осталось в примечании. В любом случае, расширить можно. Но только сами. В этой статье: Ведение журнала сделанных в книге изменений можете посмотреть реализацию запоминания старого значения и применить к данной статье.

  5. Андрей
    19 Ноябрь 2011 в 13:45 | #5

    @Дмитрий(Админ)
    Дмитрий, не могли бы Вы ответить и на вторую часть моего комментария? (про диапазон ячеек)

  6. 19 Ноябрь 2011 в 14:37 | #6

    Конечно.
    Первой строкой кода пишите:

    If Intersect(Target, Me.Range("A1:B10")) Is Nothing Then Exit Sub
    If Intersect(Target, Me.Range("A1:B10")) Is Nothing Then Exit Sub

    где «A1:B10″ это диапазон, изменения в котором отслеживаются.

  7. Андрей
    19 Ноябрь 2011 в 15:30 | #7

    @Дмитрий(Админ)
    Спасибо, работает.
    Не хочу злоупотреблять…
    Я не смог разобраться с «предыдущим значением ячейки в ком-те»
    Может за скромную плату допишите?
    (Нужно, чтобы указывалось предыдущее значение(вместо нового) и Автор изменений, если он (Автор) изменился.)
    Заранее благодарен,
    Андрей.

  8. 19 Ноябрь 2011 в 16:09 | #8

    Добавил в статью код записи прежнего значения и всего остального. Пример к статье так же изменен.

  9. Андрей
    19 Ноябрь 2011 в 16:48 | #9

    @Дмитрий(Админ)
    В коменте по прежнему отображается новое значение.
    Может я что не так вставил, (скопировал весь код и вставил как есть.)

    «Автор изменений, если он (Автор) изменился» — иначе Автор пишется каждый раз, примечание увеличивается вдвое и не несет информативности. Может это уже слишком…?

  10. 19 Ноябрь 2011 в 17:22 | #10

    Исправил ошибку про запись «прежнего» значения. А вот с автором — да, это уже слишком. Здесь надо морочиться. Андрей — либо изуйчайте VBA, либо переносим общение в личную почту.

  11. Андрей
    19 Ноябрь 2011 в 17:30 | #11

    Давайле в личку.
    Заметил ещё одну проблемку: если до этого в ячейке уже был коммкетарий, то после изменения значения ячейки текст и старый и новый становится жирным.

  12. Андрей
    21 Ноябрь 2011 в 05:37 | #12

    Дмитрий, пожалуйста удалите мои лишние посты.
    Модуль полезный, но недоделанный.
    На счет первого варианта: приведите пожалуйста пример, когда в примечании необходимо отображать значение, которое отображено в ячейке.

  13. 21 Ноябрь 2011 в 10:00 | #13

    Андрей :

    Модуль полезный, но недоделанный.
    На счет первого варианта: приведите пожалуйста пример, когда в примечании необходимо отображать значение, которое отображено в ячейке.

    Если код не выполняет условия именно ВАШЕЙ задачи, это не значит, что он недоделанный. Ищите доделанные тогда.

  14. CTR
    26 Январь 2012 в 11:23 | #14

    Дмитрий, огромаднейшее спасибо, нашел прямо то, что искал!

    Единственный вопрос: а можно ли сделать так (и как?), чтобы примечание появлялось не при первом вводе значения, а только при его изменении?

    Начальству, я думаю понравится, с премии поддержу!

  15. 26 Январь 2012 в 16:32 | #15

    В принципе можно. Но код необходимо доработать процедурой из второго кода. Если и так второй код используете, то вариант:

    Private Sub Worksheet_Change(ByVal Target As Range)
    'отслеживаем изменения только в диапазоне "A1:B10"
        If Intersect(Target, Me.Range("A1:B10")) Is Nothing Then Exit Sub
        'проверяем, было ли значение в ячейке до этого
        If sValue = ""  Then Exit Sub
        'сравниваем новое значение с прежним
        If CStr(Target.Value) <> sValue Then
    'далее все так же
    Private Sub Worksheet_Change(ByVal Target As Range)
    'отслеживаем изменения только в диапазоне "A1:B10"
        If Intersect(Target, Me.Range("A1:B10")) Is Nothing Then Exit Sub
        'проверяем, было ли значение в ячейке до этого
        If sValue = ""  Then Exit Sub
        'сравниваем новое значение с прежним
        If CStr(Target.Value) <> sValue Then
    'далее все так же
  16. CTR
    26 Январь 2012 в 16:49 | #16

    Спасибо, Дмитрий!!!
    Работает, ништяк, с меня причитается на пиво!

Комментарий будет добавлен после проверки администратором.
Комментарии, не имеющие отношения к комментируемой статье, будут удаляться без уведомления и объяснения причин. Если есть вопрос по проблеме в Excel- добро пожаловаться на Форум