Доброй ночи, уважаемые форумчане. Помогите разобраться в макросах. Я откомментировал то, что для меня понятно, прошу поправить, если я где-либо не прав и докомментировать те строки, что мне не понятны. Макросы отслеживания изменений на листе. Нашел на ресурсе эесель-вба [vba]
Код
Option Explicit
Public sValue As String ' обьявляем переменную, а какую и зачем - не понятно. Private Sub Workbook_SheetChange(ByVal Sh As Object, ByVal Target As Range) ' срабатывание при изменении на листе If Sh.Name = "LOG" Then Exit Sub ' если изменения на листе LOG - выходим из макроса Dim sLastValue As String Dim lLastRow As Long With Sheets("LOG") ' sheets("LOG"). дальнейшие диапазоны с листа LOG. lLastRow = .Cells.SpecialCells(xlLastCell).Row + 1 ' назначаем переменной последнюю строку используемого диапазона листа + 1 строку If lLastRow = Rows.Count Then Exit Sub ' не совсем понятно, но думаю, что если значение переменной = общему кол-ву возможных строк, то выходим из макроса Application.ScreenUpdating = False: Application.EnableEvents = False 'отключаем обновление экрана и еще какую-то непонятную фигню .Cells(lLastRow, 1) = Cells(Target.Cells.Row, 1).Value .Cells(lLastRow, 2) = Cells(2, Target.Cells.Column).Value .Cells(lLastRow, 3) = Target.Value If Target.Count > 1 Then 'если выделено более одной ячейки то Dim rCell As Range, rRng As Range On Error Resume Next Set rRng = Intersect(Target, Sh.UsedRange): On Error GoTo 0 ' какое-то пересечение, но не совсем понятно If Not rRng Is Nothing Then ' тут тоже не понятно For Each rCell In rRng ' перебор всех ячеек в диапазоне, но не понятно зачем If Not IsError(Target) Then sLastValue = sLastValue & "," & rCell Else sLastValue = sLastValue & "," & "Err" ' тут вообще не понятно Next rCell ' возвращаемся к перебору sLastValue = Mid(sLastValue, 2) ' не понятно совсем Else sLastValue = "" ' и тут тоже не понятно
End If Else If Not IsError(Target) Then sLastValue = Target.Value Else sLastValue = "Err" ' и тут тоже не понятно End If .Cells(lLastRow, 4).NumberFormat = "@" ' и тут тоже не понятно .Cells(lLastRow, 4) = sLastValue ' и тут тоже не понятно End With Application.ScreenUpdating = True: Application.EnableEvents = True ' включаем то, что выключили ) End Sub
' все, что ниже не понятно зачем вообще нужно, но в источнике эти два макроса идут вместе )
Private Sub Workbook_SheetSelectionChange(ByVal Sh As Object, ByVal Target As Range) If Sh.Name = "LOG" Then Exit Sub If Target.Count > 1 Then Dim rCell As Range, rRng As Range On Error Resume Next Set rRng = Intersect(Target, Sh.UsedRange): On Error GoTo 0 If rRng Is Nothing Then Exit Sub For Each rCell In rRng If Not IsError(rCell) Then sValue = sValue & "," & rCell Else sValue = sValue & "," & "Err" Next rCell sValue = Mid(sValue, 2) Else If Not IsError(Target) Then sValue = Target.Value Else sValue = "Err"
End If End Sub
[/vba]
Заранее спасибо за помощь.
Доброй ночи, уважаемые форумчане. Помогите разобраться в макросах. Я откомментировал то, что для меня понятно, прошу поправить, если я где-либо не прав и докомментировать те строки, что мне не понятны. Макросы отслеживания изменений на листе. Нашел на ресурсе эесель-вба [vba]
Код
Option Explicit
Public sValue As String ' обьявляем переменную, а какую и зачем - не понятно. Private Sub Workbook_SheetChange(ByVal Sh As Object, ByVal Target As Range) ' срабатывание при изменении на листе If Sh.Name = "LOG" Then Exit Sub ' если изменения на листе LOG - выходим из макроса Dim sLastValue As String Dim lLastRow As Long With Sheets("LOG") ' sheets("LOG"). дальнейшие диапазоны с листа LOG. lLastRow = .Cells.SpecialCells(xlLastCell).Row + 1 ' назначаем переменной последнюю строку используемого диапазона листа + 1 строку If lLastRow = Rows.Count Then Exit Sub ' не совсем понятно, но думаю, что если значение переменной = общему кол-ву возможных строк, то выходим из макроса Application.ScreenUpdating = False: Application.EnableEvents = False 'отключаем обновление экрана и еще какую-то непонятную фигню .Cells(lLastRow, 1) = Cells(Target.Cells.Row, 1).Value .Cells(lLastRow, 2) = Cells(2, Target.Cells.Column).Value .Cells(lLastRow, 3) = Target.Value If Target.Count > 1 Then 'если выделено более одной ячейки то Dim rCell As Range, rRng As Range On Error Resume Next Set rRng = Intersect(Target, Sh.UsedRange): On Error GoTo 0 ' какое-то пересечение, но не совсем понятно If Not rRng Is Nothing Then ' тут тоже не понятно For Each rCell In rRng ' перебор всех ячеек в диапазоне, но не понятно зачем If Not IsError(Target) Then sLastValue = sLastValue & "," & rCell Else sLastValue = sLastValue & "," & "Err" ' тут вообще не понятно Next rCell ' возвращаемся к перебору sLastValue = Mid(sLastValue, 2) ' не понятно совсем Else sLastValue = "" ' и тут тоже не понятно
End If Else If Not IsError(Target) Then sLastValue = Target.Value Else sLastValue = "Err" ' и тут тоже не понятно End If .Cells(lLastRow, 4).NumberFormat = "@" ' и тут тоже не понятно .Cells(lLastRow, 4) = sLastValue ' и тут тоже не понятно End With Application.ScreenUpdating = True: Application.EnableEvents = True ' включаем то, что выключили ) End Sub
' все, что ниже не понятно зачем вообще нужно, но в источнике эти два макроса идут вместе )
Private Sub Workbook_SheetSelectionChange(ByVal Sh As Object, ByVal Target As Range) If Sh.Name = "LOG" Then Exit Sub If Target.Count > 1 Then Dim rCell As Range, rRng As Range On Error Resume Next Set rRng = Intersect(Target, Sh.UsedRange): On Error GoTo 0 If rRng Is Nothing Then Exit Sub For Each rCell In rRng If Not IsError(rCell) Then sValue = sValue & "," & rCell Else sValue = sValue & "," & "Err" Next rCell sValue = Mid(sValue, 2) Else If Not IsError(Target) Then sValue = Target.Value Else sValue = "Err"
Честно говоря, ковырять чужой код даже не зная что он должен делать, лень. А где Вы его взяли? Автора спросить нельзя? Судя по стилю программирования и именам переменных - это кто-то из местных или с Планеты. Код, похоже, должен вести какой-то лог изменений на листах книги... Но какой-то странный - без указания листов, на которых происходили изменения, а только адресов изменяемых ячеек или просто специфический? Размещаться код явно должен в модуле ЭтаКнига. Но тогда строки [vba]
[/vba] ИМХО не совсем корректны, т.к. "родитель" - не лист и ячеек не имеет. Поэтому возможно неоднозначное срабатывание. [vba]
Код
Application.EnableEvents = False
[/vba] - отключение реакции приложения на события. [vba]
Код
On Error Resume Next Set rRng = Intersect(Target, Sh.UsedRange): On Error GoTo 0
[/vba] вообще не вижу смысла включать обработчик ошибок, производить действие, которое не может вызвать ошибку, а потом отключать обработчик.
В общем, много чего странно-непонятного. Вы уж лучше автора попытайте или хоть скажите, где взяли и что должно делать.
Честно говоря, ковырять чужой код даже не зная что он должен делать, лень. А где Вы его взяли? Автора спросить нельзя? Судя по стилю программирования и именам переменных - это кто-то из местных или с Планеты. Код, похоже, должен вести какой-то лог изменений на листах книги... Но какой-то странный - без указания листов, на которых происходили изменения, а только адресов изменяемых ячеек или просто специфический? Размещаться код явно должен в модуле ЭтаКнига. Но тогда строки [vba]
Да, похоже на Димин стиль. Я даже в посте сначала про это написал и ссылку на его "Что умеет..." дал. Но потом посмотрел внимательно на код, увидел ляпы и решил, что это кто-то из учеников мастера ваял, а потому ссылку стёр.
Да, похоже на Димин стиль. Я даже в посте сначала про это написал и ссылку на его "Что умеет..." дал. Но потом посмотрел внимательно на код, увидел ляпы и решил, что это кто-то из учеников мастера ваял, а потому ссылку стёр.Alex_ST
здесь да, согласен Intersect единственно тогда "умирает", когда идет попытка перехлестнуть диапазоны с разных листов/книг здесь заведомо такое невозможно
Цитата (Alex_ST)
.Cells(lLastRow, 1) = ...
Леша, что ты? Там же вверху [vba]
Код
With Sheets("LOG")
[/vba]
Цитата (Alex_ST)
On Error Resume ....
здесь да, согласен Intersect единственно тогда "умирает", когда идет попытка перехлестнуть диапазоны с разных листов/книг здесь заведомо такое невозможноСаня
[/vba] Эти две строки я добавил =\ (видимо криво) но другой вариант добавить название столбца (шапки листа) и значения из первого столбца (для идентификации строки в которой были изменения) я не придумал.
И если хоть часть первого макроса я еще понимаю, то второй для меня остается загадкой.
PS: Да, это макрос для модуля листа. ПРошу прощения, что не указал это при создании темы.
[/vba] Эти две строки я добавил =\ (видимо криво) но другой вариант добавить название столбца (шапки листа) и значения из первого столбца (для идентификации строки в которой были изменения) я не придумал.
И если хоть часть первого макроса я еще понимаю, то второй для меня остается загадкой.
PS: Да, это макрос для модуля листа. ПРошу прощения, что не указал это при создании темы.SkyPro
skypro1111@gmail.com
Сообщение отредактировал SkyPro - Четверг, 27.06.2013, 00:05
Саня, посмотри внимательно на названия и аргументы обработчиков событий - это ЯВНО обработчики событий не ЛИСТА, а КНИГИ. И если разместить такие коды в модуле листа, то события просто не возникнут (хотя, чем чёрт не шутит - просто никогда даже в голову не приходило их туда попробовать засунуть - а вдруг заработают?)
Цитата (SkyPro)
это макрос для модуля листа
что-то сильно сомневаюсь, что события книги будут обрабатываться в модуле листа... А что Вам мешает разместить эти коды правильно - в модуле ЭтаКнига - и чуть подправить код: вместо Cells писать Sh.Cells? И почему бы Вам не задавать вопросы по функционированию и доработке макроса там, где Вы его взяли - у Дмитрия (The_Prist) в теме Ведение журнала сделанных в книге изменений или на его же Форуме?
Поймите, странность и некорректность ситуации. Ведь мы же, Excel-маны , все общаемся на нескольких форумах одновременно и друг друга знаем достаточно хорошо. Ведь не с проста же я сразу сказал, что стиль программирования мне кажется знакомым и быстро нашёл, откуда "ноги растут". А Вы на другом сайте взяли готовый код, написанный нашим другом, но почему-то скрываете первоисточник. Сразу возникает законный вопрос: "Вы с Димой что-то не поделили?" Тогда извините, но он наш друг и помогать Вам тут мало кто захочет. А потом Вы как-то сами доработали код, не объясняя, что в результате хотели получить. И теперь пытаетесь ЗДЕСЬ разобраться, как "исправленный" Вами код работает. Мы гадать должны о Ваших задумках?
Саня, посмотри внимательно на названия и аргументы обработчиков событий - это ЯВНО обработчики событий не ЛИСТА, а КНИГИ. И если разместить такие коды в модуле листа, то события просто не возникнут (хотя, чем чёрт не шутит - просто никогда даже в голову не приходило их туда попробовать засунуть - а вдруг заработают?)
Цитата (SkyPro)
это макрос для модуля листа
что-то сильно сомневаюсь, что события книги будут обрабатываться в модуле листа... А что Вам мешает разместить эти коды правильно - в модуле ЭтаКнига - и чуть подправить код: вместо Cells писать Sh.Cells? И почему бы Вам не задавать вопросы по функционированию и доработке макроса там, где Вы его взяли - у Дмитрия (The_Prist) в теме Ведение журнала сделанных в книге изменений или на его же Форуме?
Поймите, странность и некорректность ситуации. Ведь мы же, Excel-маны , все общаемся на нескольких форумах одновременно и друг друга знаем достаточно хорошо. Ведь не с проста же я сразу сказал, что стиль программирования мне кажется знакомым и быстро нашёл, откуда "ноги растут". А Вы на другом сайте взяли готовый код, написанный нашим другом, но почему-то скрываете первоисточник. Сразу возникает законный вопрос: "Вы с Димой что-то не поделили?" Тогда извините, но он наш друг и помогать Вам тут мало кто захочет. А потом Вы как-то сами доработали код, не объясняя, что в результате хотели получить. И теперь пытаетесь ЗДЕСЬ разобраться, как "исправленный" Вами код работает. Мы гадать должны о Ваших задумках?Alex_ST
посмотри внимательно на названия и аргументы обработчиков событий
Зачем? Я прекрасно различаю эти вещи: [vba]
Код
Private Sub Worksheet_Change(ByVal Target As Range) Private Sub Worksheet_SelectionChange(ByVal Target As Range)
Private Sub Workbook_SheetChange(ByVal Sh As Object, ByVal Target As Range) Private Sub Workbook_SheetSelectionChange(ByVal Sh As Object, ByVal Target As Range)
[/vba]
Цитата (Alex_ST)
И если разместить такие коды в модуле листа, то события просто не возникнут biggrin (хотя, чем чёрт не шутит - просто никогда даже в голову не приходило их туда попробовать засунуть - а вдруг заработают?)
не заработают, не сомневайся - это будут просто приватные процедуры/методы класса
у меня есть подозрение, что происходит все след. образом: 1) модуль листа. Cells - есть свойство класса Worksheet, поэтому компилятор воспринимает это как Me.Cells
2) модуль книги Cells - несуществующее свойство объекта Workbook, поэтому компилятор ищет в global-объектах
работает именно так.
Цитата (Alex_ST)
посмотри внимательно на названия и аргументы обработчиков событий
Зачем? Я прекрасно различаю эти вещи: [vba]
Код
Private Sub Worksheet_Change(ByVal Target As Range) Private Sub Worksheet_SelectionChange(ByVal Target As Range)
Private Sub Workbook_SheetChange(ByVal Sh As Object, ByVal Target As Range) Private Sub Workbook_SheetSelectionChange(ByVal Sh As Object, ByVal Target As Range)
[/vba]
Цитата (Alex_ST)
И если разместить такие коды в модуле листа, то события просто не возникнут biggrin (хотя, чем чёрт не шутит - просто никогда даже в голову не приходило их туда попробовать засунуть - а вдруг заработают?)
не заработают, не сомневайся - это будут просто приватные процедуры/методы класса
у меня есть подозрение, что происходит все след. образом: 1) модуль листа. Cells - есть свойство класса Worksheet, поэтому компилятор воспринимает это как Me.Cells
2) модуль книги Cells - несуществующее свойство объекта Workbook, поэтому компилятор ищет в global-объектах
Поймите, странность и некорректность ситуации. Ведь мы же, Excel-маны , все общаемся на нескольких форумах одновременно и друг друга знаем достаточно хорошо. Ведь не с проста же я сразу сказал, что стиль программирования мне кажется знакомым и быстро нашёл, откуда "ноги растут". А Вы на другом сайте взяли готовый код, написанный нашим другом, но почему-то скрываете первоисточник.
Я прекрасно понимаю, что вы, гуру экселя (это не сарказм), друг друга знаете. И я источник указал в первом посте
Цитата
Макросы отслеживания изменений на листе. Нашел на ресурсе эесель-вба
(просто думал, что ссылку на другой ресурс могут приять за рекламу).
Обратился сюда, а не на форум "источника", так как знаю, что среди здешних есть достаточно адекватных и очень умных людей, которые смогут помочь, а что делается на том форуме - не вкурсе.
Код изменен только в тех строках, где записываются значения ячеек листа "LOG". Тоесть в строках, которые на выполнение самого макроса не должны влиять.
ЗЫ: Уважаемые, если я нарушил правила форума, или чем-либо вас обидел, то прошу закрыть и забыть эту тему (правда вы и так своей дискусией подкинули мне пищу для ума, за что отдельное спасибо). Я просто попросил помощи.
ЗЫЗЫ: Простите еще и мою невнимательность.. Да, действительно это код модуля книги, как и указано в источнике.
Цитата (Alex_ST)
Поймите, странность и некорректность ситуации. Ведь мы же, Excel-маны , все общаемся на нескольких форумах одновременно и друг друга знаем достаточно хорошо. Ведь не с проста же я сразу сказал, что стиль программирования мне кажется знакомым и быстро нашёл, откуда "ноги растут". А Вы на другом сайте взяли готовый код, написанный нашим другом, но почему-то скрываете первоисточник.
Я прекрасно понимаю, что вы, гуру экселя (это не сарказм), друг друга знаете. И я источник указал в первом посте
Цитата
Макросы отслеживания изменений на листе. Нашел на ресурсе эесель-вба
(просто думал, что ссылку на другой ресурс могут приять за рекламу).
Обратился сюда, а не на форум "источника", так как знаю, что среди здешних есть достаточно адекватных и очень умных людей, которые смогут помочь, а что делается на том форуме - не вкурсе.
Код изменен только в тех строках, где записываются значения ячеек листа "LOG". Тоесть в строках, которые на выполнение самого макроса не должны влиять.
ЗЫ: Уважаемые, если я нарушил правила форума, или чем-либо вас обидел, то прошу закрыть и забыть эту тему (правда вы и так своей дискусией подкинули мне пищу для ума, за что отдельное спасибо). Я просто попросил помощи.
ЗЫЗЫ: Простите еще и мою невнимательность.. Да, действительно это код модуля книги, как и указано в источнике.SkyPro
skypro1111@gmail.com
Сообщение отредактировал SkyPro - Четверг, 27.06.2013, 21:28
Ну, даже странно... Вы форум Димы (The_Prist) пролистывали? Это там-то недостаточно адекватных, умных и, главное, ТЕРПЕЛИВЫХ людей? Да Дима - один из первой десятки самых знающих и умеющих разъяснять гуру! Тут очень многие нынешние знатоки познавали азы по его программам и под его руководством. Не даром же я говорил о знакомом стиле программирования и наименования переменных. Это его стиль, который теперь уже переняли многие. И я сам по его программам учился. На самом деле Вы ничего не нарушили и, кажется, никого не обидели, но просто корректнее всего было бы обратиться к Диме.
Ну а если всё-таки хотите получить помощь здесь, то излагайте словами алгоритм: что и где есть (структура книги), что, где и в каком виде хотите получить и по каким событиям в книге. Прилагайте файл-пример со своими наработками (в соответствии с Правилами форума). Тогда будем разбираться, что и почему не работает.
Ну, даже странно... Вы форум Димы (The_Prist) пролистывали? Это там-то недостаточно адекватных, умных и, главное, ТЕРПЕЛИВЫХ людей? Да Дима - один из первой десятки самых знающих и умеющих разъяснять гуру! Тут очень многие нынешние знатоки познавали азы по его программам и под его руководством. Не даром же я говорил о знакомом стиле программирования и наименования переменных. Это его стиль, который теперь уже переняли многие. И я сам по его программам учился. На самом деле Вы ничего не нарушили и, кажется, никого не обидели, но просто корректнее всего было бы обратиться к Диме.
Ну а если всё-таки хотите получить помощь здесь, то излагайте словами алгоритм: что и где есть (структура книги), что, где и в каком виде хотите получить и по каким событиям в книге. Прилагайте файл-пример со своими наработками (в соответствии с Правилами форума). Тогда будем разбираться, что и почему не работает.Alex_ST
В файле есть лист "1" и лист "log". Необходимо отслеживать изменения на листе 1 и записывать произошедшие изменения на лист "log". В зафиксированных данных должно быть значение ячейки, которое было до изменения, после изменения, значение из столбца 1 (ID) и соответствующей измененной ячейке строки, и значение из строки 1 (шапка) и соответствующего измененной ячейке столбца. Пример файла и первичный вариант макроса (делал по примеру макросов с excel-vba.ru): [vba]
Код
Option Explicit ' обьясните что эта фигня делает <img src="http://s5.ucoz.net/sm/1/smile.gif" border="0" align="absmiddle" alt="smile" /> Public bChange As String ' обьявляем переменную для всех макросов
Private Sub Workbook_SheetChange(ByVal Sh As Object, ByVal Target As Range) ' срабатывание макроса при любом изменении на листе (кроме автопересчета формул) If Sh.Name = "log" Then Exit Sub ' если активен лист log -выходим из макроса Dim lrow As Long
Application.ScreenUpdating = False: Application.EnableEvents = False ' отключаем обновление экрана и (еле допер зачем это) обработку событий, что бы не установилось новое значение bChange до записи на лист log
Sheets("log").Cells(lrow, 1) = Cells(Target.Cells.Row, 1).Value ' записываем значение из столбца ID и соответствующей измененной ячейки строки Sheets("log").Cells(lrow, 2) = Cells(1, Target.Cells.Column).Value ' записываем значение из первой строки и соответствующего измененной ячейки столбца (шапка) Sheets("log").Cells(lrow, 3) = bChange ' записываем значение ячейки до изменения (вот зачем был следующий макрос) Sheets("log").Cells(lrow, 4) = Target.Value ' записываем измененное значение ячейки
Application.ScreenUpdating = True: Application.EnableEvents = True ' включаем обновление экрана и обработку событий
End Sub
Private Sub Workbook_SheetSelectionChange(ByVal Sh As Object, ByVal Target As Range) ' срабатывание макроса на выбор ячейки\диапазона If Sh.Name = "log" Then Exit Sub ' если активен лист log -выходим из макроса If Target.Count > 1 Then Exit Sub ' пока отключаем выбор диапазона, нужно подумать. bChange = Target.Value ' назначаем глобальной (если не правильное название - поправьте) переменной значение выбраного диапазона End Sub
[/vba] Макрос модуля книги. Где я ошибся? ЗЫ: в процессе проверка на "ложные изменения" и выбор диапазона.
В файле есть лист "1" и лист "log". Необходимо отслеживать изменения на листе 1 и записывать произошедшие изменения на лист "log". В зафиксированных данных должно быть значение ячейки, которое было до изменения, после изменения, значение из столбца 1 (ID) и соответствующей измененной ячейке строки, и значение из строки 1 (шапка) и соответствующего измененной ячейке столбца. Пример файла и первичный вариант макроса (делал по примеру макросов с excel-vba.ru): [vba]
Код
Option Explicit ' обьясните что эта фигня делает <img src="http://s5.ucoz.net/sm/1/smile.gif" border="0" align="absmiddle" alt="smile" /> Public bChange As String ' обьявляем переменную для всех макросов
Private Sub Workbook_SheetChange(ByVal Sh As Object, ByVal Target As Range) ' срабатывание макроса при любом изменении на листе (кроме автопересчета формул) If Sh.Name = "log" Then Exit Sub ' если активен лист log -выходим из макроса Dim lrow As Long
Application.ScreenUpdating = False: Application.EnableEvents = False ' отключаем обновление экрана и (еле допер зачем это) обработку событий, что бы не установилось новое значение bChange до записи на лист log
Sheets("log").Cells(lrow, 1) = Cells(Target.Cells.Row, 1).Value ' записываем значение из столбца ID и соответствующей измененной ячейки строки Sheets("log").Cells(lrow, 2) = Cells(1, Target.Cells.Column).Value ' записываем значение из первой строки и соответствующего измененной ячейки столбца (шапка) Sheets("log").Cells(lrow, 3) = bChange ' записываем значение ячейки до изменения (вот зачем был следующий макрос) Sheets("log").Cells(lrow, 4) = Target.Value ' записываем измененное значение ячейки
Application.ScreenUpdating = True: Application.EnableEvents = True ' включаем обновление экрана и обработку событий
End Sub
Private Sub Workbook_SheetSelectionChange(ByVal Sh As Object, ByVal Target As Range) ' срабатывание макроса на выбор ячейки\диапазона If Sh.Name = "log" Then Exit Sub ' если активен лист log -выходим из макроса If Target.Count > 1 Then Exit Sub ' пока отключаем выбор диапазона, нужно подумать. bChange = Target.Value ' назначаем глобальной (если не правильное название - поправьте) переменной значение выбраного диапазона End Sub
[/vba] Макрос модуля книги. Где я ошибся? ЗЫ: в процессе проверка на "ложные изменения" и выбор диапазона.SkyPro
А в чём проблема? У Вас всё работает. Ну разве что чуть "причесать" для красоты и откомментировать примерно так:[vba]
Код
Option Explicit ' команда компилятору требовать объявления переменные - это не обязательно, но желательно для упрощения отладки. И вообще является признаком хорошего тона в программировании <img src="http://s5.ucoz.net/sm/1/smile.gif" border="0" align="absmiddle" alt="smile" /> Dim vPrevious_Value ' переменная, в которую будут записываться предыдущие перед изменением значения ячеек
Private Sub Workbook_SheetChange(ByVal Sh As Object, ByVal Target As Range) ' процедура, автоматически вызываемая приложением при любом изменении на любом листе (кроме автопересчета формул) If Sh.Name = "log" Then Exit Sub ' если активен лист log, выходим Dim lRow As Long ' переменная для хранения номера первой пустой строки листа "log" lRow = Sheets("log").Cells.SpecialCells(xlLastCell).Row + 1 ' находим номер первой пустой строки листа "log" чтобы в неё записывать данные Application.ScreenUpdating = False: Application.EnableEvents = False ' отключаем обновление экрана (чтобы не моргал) и обработку событий (чтобы не реагировало на запись на лист log и не было зацикливания) With Sheets("log") ' на листе "log" … .Cells(lRow, 1) = Sh.Cells(Target.Cells.Row, 1).Value ' … в строке lRow в ячейку столбца 1 записываем значение из ячейки столбца 1 - ID строки .Cells(lRow, 2) = Sh.Cells(1, Target.Cells.Column).Value ' … в строке lRow в ячейку столбца 2 записываем значение из ячейки строки 1 - шапка .Cells(lRow, 3) = vPrevious_Value ' … в строке lRow в ячейку столбца 3 записываем значение ячейки до изменения .Cells(lRow, 4) = Target.Value ' … в строке lRow в ячейку столбца 4 записываем новое значение ячейки End With Application.ScreenUpdating = True: Application.EnableEvents = True ' включаем обновление экрана и обработку событий End Sub
Private Sub Workbook_SheetSelectionChange(ByVal Sh As Object, ByVal Target As Range) ' процедура, автоматически вызываемая приложением при КАЖДОМ изменении выбранного диапазона If Sh.Name = "log" Then Exit Sub ' если активен лист log, выходим If Target.Count > 1 Then Exit Sub ' если выбрано больше одной ячейки, выходим vPrevious_Value = Target.Value ' запоминаем значение ячейки до изменения End Sub
[/vba]
А в чём проблема? У Вас всё работает. Ну разве что чуть "причесать" для красоты и откомментировать примерно так:[vba]
Код
Option Explicit ' команда компилятору требовать объявления переменные - это не обязательно, но желательно для упрощения отладки. И вообще является признаком хорошего тона в программировании <img src="http://s5.ucoz.net/sm/1/smile.gif" border="0" align="absmiddle" alt="smile" /> Dim vPrevious_Value ' переменная, в которую будут записываться предыдущие перед изменением значения ячеек
Private Sub Workbook_SheetChange(ByVal Sh As Object, ByVal Target As Range) ' процедура, автоматически вызываемая приложением при любом изменении на любом листе (кроме автопересчета формул) If Sh.Name = "log" Then Exit Sub ' если активен лист log, выходим Dim lRow As Long ' переменная для хранения номера первой пустой строки листа "log" lRow = Sheets("log").Cells.SpecialCells(xlLastCell).Row + 1 ' находим номер первой пустой строки листа "log" чтобы в неё записывать данные Application.ScreenUpdating = False: Application.EnableEvents = False ' отключаем обновление экрана (чтобы не моргал) и обработку событий (чтобы не реагировало на запись на лист log и не было зацикливания) With Sheets("log") ' на листе "log" … .Cells(lRow, 1) = Sh.Cells(Target.Cells.Row, 1).Value ' … в строке lRow в ячейку столбца 1 записываем значение из ячейки столбца 1 - ID строки .Cells(lRow, 2) = Sh.Cells(1, Target.Cells.Column).Value ' … в строке lRow в ячейку столбца 2 записываем значение из ячейки строки 1 - шапка .Cells(lRow, 3) = vPrevious_Value ' … в строке lRow в ячейку столбца 3 записываем значение ячейки до изменения .Cells(lRow, 4) = Target.Value ' … в строке lRow в ячейку столбца 4 записываем новое значение ячейки End With Application.ScreenUpdating = True: Application.EnableEvents = True ' включаем обновление экрана и обработку событий End Sub
Private Sub Workbook_SheetSelectionChange(ByVal Sh As Object, ByVal Target As Range) ' процедура, автоматически вызываемая приложением при КАЖДОМ изменении выбранного диапазона If Sh.Name = "log" Then Exit Sub ' если активен лист log, выходим If Target.Count > 1 Then Exit Sub ' если выбрано больше одной ячейки, выходим vPrevious_Value = Target.Value ' запоминаем значение ячейки до изменения End Sub
Обратился сюда, а не на форум "источника", так как знаю, что среди здешних есть достаточно адекватных и очень умных людей, которые смогут помочь, а что делается на том форуме - не вкурсе.
- отвратительно!
Цитата (Alex_ST)
Вы форум Димы (The_Prist) пролистывали?
Леш, ну это даже в комментах не нуждается, нафиг было продолжать? Дальнейшее обсуждение, плиз, в личку.
Цитата (SkyPro)
Обратился сюда, а не на форум "источника", так как знаю, что среди здешних есть достаточно адекватных и очень умных людей, которые смогут помочь, а что делается на том форуме - не вкурсе.
- отвратительно!
Цитата (Alex_ST)
Вы форум Димы (The_Prist) пролистывали?
Леш, ну это даже в комментах не нуждается, нафиг было продолжать? Дальнейшее обсуждение, плиз, в личку.KuklP
Ну с НДС и мы чего-то стoим! kuklp60@gmail.com WM Z206653985942, R334086032478, U238399322728