powered by simpleCommunicator - 2.0.39     © 2025 Programmizd 02
Форумы / Microsoft Office [игнор отключен] [закрыт для гостей] / vba excel Как получить старое значение ячеек до изменения
7 сообщений из 7, страница 1 из 1
vba excel Как получить старое значение ячеек до изменения
    #38794566
vuler
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Вот исходник для ведения лога
Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
   Option Explicit
Const Sep$ = "; " ' разделитель при перечислении значений ячеек
Const MaxCells% = 16 ' максимальное количество значений ячеек при их перечислении
Dim sOldValue As String
Dim sOldarr1()

Private Sub Workbook_SheetChange(ByVal Sh As Object, ByVal Target As Range)
   Application.EnableEvents = True
   '---------------------------------------------------------------------------------------
   ' Procedure : Workbook_SheetChange
   ' Author    : The_Prist (идея) & Alex_St (доработка)
   ' URL       : http://www.excel-vba.ru/index.php?file=Tips_Macro_Log
   ' Date      :
   ' Purpose   : Ведение ЛОГ-файла произведенных изменений на листе LOG
   ' Notes     :
   '---------------------------------------------------------------------------------------
   If Sh.Name = "LOG" Then Exit Sub
   Dim sNewValue As String
   Dim lLastRow As Long
   Dim rCell As Range
    'MsgBox "Тут"
    Dim cur_line As Integer
   Dim vag_col As Integer
   vag_col = 2
   
   With Sheets("LOG")
      
      'incriser = lLastRow + 1
      If Not Intersect(Target, Sh.UsedRange) Is Nothing Then
         If Target.Count > 1 Then
            cur_line = 1
            
            For Each rCell In Intersect(Target, Sh.UsedRange)
             lLastRow = .UsedRange.Row + .UsedRange.Rows.Count
      If lLastRow = .Rows.Count Then Exit Sub
                MsgBox "change"
                Application.ScreenUpdating = False: Application.EnableEvents = False
                .Cells(lLastRow, 1) = CreateObject("wscript.network").UserName
                .Cells(lLastRow, 2) = Format(Now, "dd.mm.yyyy HH:MM:SS")
                .Cells(lLastRow, 3) = Sh.Name
                .Cells(lLastRow, 4) = Target.Address(0, 0)
                .Cells(lLastRow, 5) = sOldarr1(cur_line)
                .Cells(lLastRow, 6) = rCell
                .Cells(lLastRow, 7) = Cells(rCell.Row, vag_col)
               'If Not IsError(Target) Then sNewValue = sNewValue & Sep & rCell Else sNewValue = sNewValue & Sep & "Err"
               'If UBound(Split(sNewValue, Sep)) > MaxCells - 1 Then sNewValue = sNewValue & Sep & "...": Exit For
                 cur_line = cur_line + 1
            Next rCell
            'sNewValue = Mid(sNewValue, Len(Sep) + 1)
         Else
                lLastRow = .UsedRange.Row + .UsedRange.Rows.Count
                If lLastRow = .Rows.Count Then Exit Sub
                Application.ScreenUpdating = False: Application.EnableEvents = False
                .Cells(lLastRow, 1) = CreateObject("wscript.network").UserName
                .Cells(lLastRow, 2) = Format(Now, "dd.mm.yyyy HH:MM:SS")
                .Cells(lLastRow, 3) = Sh.Name
                .Cells(lLastRow, 4) = Target.Address(0, 0)
                .Cells(lLastRow, 5) = sOldValue
                .Cells(lLastRow, 6) = Target.Value
                .Cells(lLastRow, 7) = Cells(Target.Row, vag_col)
                'MsgBox Target.Value
            If Not IsError(Target) Then sNewValue = Target.Value Else sNewValue = "Err"
         End If
      End If
     ' .Cells(lLastRow, 6) = sNewValue
   End With
   Application.ScreenUpdating = True: Application.EnableEvents = True
End Sub

Private Sub Workbook_SheetSelectionChange(ByVal Sh As Object, ByVal Target As Range)
   Dim rCell As Range, i%
   'Dim sOldValue()
   Dim cur_line As Integer
   'MsgBox Target.Count
   
   'sOldValue = ""
   If Sh.Name = "LOG" Then Exit Sub
   cur_line = 1
   If Not Intersect(Target, Sh.UsedRange) Is Nothing Then
      cur_line = 1
      MsgBox Target.Count
      If Target.Count > 1 Then
                ReDim sOldarr1(1 To Target.Count)
         For Each rCell In Intersect(Target, Sh.UsedRange)
                sOldarr1(cur_line) = rCell
                cur_line = cur_line + 1
         Next rCell
         'sOldValue = Mid(sOldValue, Len(Sep) + 1)
      Else
         If Not IsError(Target) Then sOldValue = Target.Value Else sOldValue = "Err"
      End If
   End If
End Sub


Тут все изменения на листах записываются на лист ЛОГ.
Проблема состоит в следующем. Если изменяется одна ячейка, то все работает хорошо. Но если изменяется сразу несколько ячеек, то работает не всегда корректно. Если пользователь сначала выделяет диапазон, а потом жмет ctrl+v - все работает хорошо, но вот если он выделит одну ячейку и нажмет ctrl+v, и вставит сразу несколько ячеек из буфера, то в ЛОГ запишутся значения которые он вставит, а не которые были в этих ячейках до этого. Можно как-то это обойти??
...
Рейтинг: 0 / 0
vba excel Как получить старое значение ячеек до изменения
    #38794618
Фотография The_Prist
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
vuler,

Как вариант использовать метод .Undo.
Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
Private Sub Worksheet_Change(ByVal Target As Range)
    Dim vVal, vOldVal
    With Application
        vVal = Target.Value
        .EnableEvents = 0
        .Undo
        vOldVal = Target.Value
        Target.Value = vVal
        .EnableEvents = 1
    End With
End Sub


С форматами, правда, беда будет. Но значения все можно запомнить.
...
Рейтинг: 0 / 0
vba excel Как получить старое значение ячеек до изменения
    #38794625
Фотография AndreTM
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Честно говоря, не вижу смысла в вопросе. Вы хотите логировать то, что было в ячейках и до, и после изменения? А зачем? То, что было ДО - находится из анализа вашего же лога (если есть бэкап исходника и лог "акций" - то получить состояние можно на любой момент).

Но, в принципе... В коде Change нет запоминания значения при Target.Count=1 , т.е. как раз при выборе одной ячейки. Вот поэтому у вас выбор нескольких ячеек - запоминает старые значения, а выбор одной - нет.
Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
      ...
      Dim sOldValue
      ...
      If Target.Count > 1 Then
      ...
      Else
      ...
         sOldValue=Target.Value
      End If
      ...
...
Рейтинг: 0 / 0
vba excel Как получить старое значение ячеек до изменения
    #38794628
Фотография The_Prist
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
AndreTM,

Не в этом дело. Имеется ввиду, что выделение одной как раз запоминается. Но когда выделили одну и сделали вставку нескольких ячеек - то запомнилась лишь одна ячейка старого значения, в то время как новых ячеек может быть больше - сколько скопировали, столько вставится.
...
Рейтинг: 0 / 0
vba excel Как получить старое значение ячеек до изменения
    #38794649
Фотография AndreTM
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
А, если так - то да...
Но я всё же за то, что старые значения вообще не надо запоминать
...
Рейтинг: 0 / 0
vba excel Как получить старое значение ячеек до изменения
    #38794694
Фотография The_Prist
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
AndreTM,

Я не совсем согласен, но...Я за такой подход, что изменения отслеживать перед закрытием книги с сохранением. Перед открытием делать копию листа/книги, а перед закрытием сверять, какие значения были изменены. И для расходования ресурсов оптимально и значения реально измененные только отследит без лишнего хлама.
...
Рейтинг: 0 / 0
vba excel Как получить старое значение ячеек до изменения
    #38794781
Фотография AndreTM
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ну, я немного неправильно выразился. Нн надо запоминать "старые значения изменяемых ячеек ".
Т.е. стандартный транзакционный подход: имеется полная копия (бэкап) книги, по состоянию на некоторый момент, и имеется лог действий, произведенных над книгой, начиная с этого момента. И этого достаточно...
...
Рейтинг: 0 / 0
7 сообщений из 7, страница 1 из 1
Форумы / Microsoft Office [игнор отключен] [закрыт для гостей] / vba excel Как получить старое значение ячеек до изменения
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]