Здравствуйте. Есть идея вести лог изменений заполненных ячеек. Если пустая ячейка заполняется то вносить это в лог не надо. В логе должна содержатся старая и новая информация. И каким-то образом должно быть понятно из какой это было ячейки. И сразу доп вопрос VBA сможет писать лог на скрытую страницу которая будет доступна по определенному паролю ?
Здравствуйте. Есть идея вести лог изменений заполненных ячеек. Если пустая ячейка заполняется то вносить это в лог не надо. В логе должна содержатся старая и новая информация. И каким-то образом должно быть понятно из какой это было ячейки. И сразу доп вопрос VBA сможет писать лог на скрытую страницу которая будет доступна по определенному паролю ?koyaanisqatsi
И сразу доп вопрос VBA сможет писать лог на скрытую страницу которая будет доступна по определенному паролю
VBA сможет - но тогда будет недоступна функция отмены действия. Есть несколько вариантов: Самый простой - сделать книгу "общей" Рецензирование -- защитить книгу и дать общий доступ. - Это штатное средство excel С использованием ВБА: Делать как Вы написали и вести лог на отдельный лист. Записывать изменения в примечания к ячейке например так. Недостатки как и выше + неудобно сводить такие данные Записывать изменения в отдельный массив, и выгружать его на лист при сохранении или закрытии - если будет какой-то сбой макроса - все изменения и массив потеряются. Но будут доступна отмена действий. Записывать изменения в отдельный ТХТ(СSV) файл - самый оптимальный способ. Такие Лог файлы ведутся многими системами - из неудобств - нужно будет его импортировать, чтобы обработать информацию, или только смотреть.
ЗЫ в первой ссылке - есть и примеры почти всех способов.
И сразу доп вопрос VBA сможет писать лог на скрытую страницу которая будет доступна по определенному паролю
VBA сможет - но тогда будет недоступна функция отмены действия. Есть несколько вариантов: Самый простой - сделать книгу "общей" Рецензирование -- защитить книгу и дать общий доступ. - Это штатное средство excel С использованием ВБА: Делать как Вы написали и вести лог на отдельный лист. Записывать изменения в примечания к ячейке например так. Недостатки как и выше + неудобно сводить такие данные Записывать изменения в отдельный массив, и выгружать его на лист при сохранении или закрытии - если будет какой-то сбой макроса - все изменения и массив потеряются. Но будут доступна отмена действий. Записывать изменения в отдельный ТХТ(СSV) файл - самый оптимальный способ. Такие Лог файлы ведутся многими системами - из неудобств - нужно будет его импортировать, чтобы обработать информацию, или только смотреть.
ЗЫ в первой ссылке - есть и примеры почти всех способов.SLAVICK
Иногда все проще чем кажется с первого взгляда.
Сообщение отредактировал SLAVICK - Пятница, 15.04.2016, 11:11
SLAVICK, Лог весьма скромный может быть, если вообще будет. Лог хочется для того чтобы можно было судить при отверждении двух людей что один написал другой не видел. Если Того о чем первый говорит нет то в логе можно посмотреть сохраненное изменение. Если в лог не попало тогда первый говорит не правду. Так как обычно спорных ситуаций не происходит то и лог будет если будет весьма скромный. Так же это актуально не в случае удаления информации а если информация корректируется но таких случаем тоже очень мало. Но не смотря что это все редкость это при возникновении вопроса очень серьезный камень преткновения.
SLAVICK, Лог весьма скромный может быть, если вообще будет. Лог хочется для того чтобы можно было судить при отверждении двух людей что один написал другой не видел. Если Того о чем первый говорит нет то в логе можно посмотреть сохраненное изменение. Если в лог не попало тогда первый говорит не правду. Так как обычно спорных ситуаций не происходит то и лог будет если будет весьма скромный. Так же это актуально не в случае удаления информации а если информация корректируется но таких случаем тоже очень мало. Но не смотря что это все редкость это при возникновении вопроса очень серьезный камень преткновения.koyaanisqatsi
SLAVICK, Мне кстати даже первый вариант бы очень подошел. [vba]
Код
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 Set oComment = 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") oComment.Shape.TextFrame.AutoSize = True End If End Sub
[/vba]
Вставил этот код на лист "Овощи"
только на листе доступном высшему руководству должна быть какая-то кнопа сбрасывать логи. (На листе "доп" ирархия доступа обозначена.) пароли доступа: Шеф 111 Овощи 222 Мясо 333 Бакалея 444
И при общем доступе не подписывает в примечании какой юзер сделал данное изменение. А это тоже важно.
SLAVICK, Мне кстати даже первый вариант бы очень подошел. [vba]
Код
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 Set oComment = 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") oComment.Shape.TextFrame.AutoSize = True End If End Sub
[/vba]
Вставил этот код на лист "Овощи"
только на листе доступном высшему руководству должна быть какая-то кнопа сбрасывать логи. (На листе "доп" ирархия доступа обозначена.) пароли доступа: Шеф 111 Овощи 222 Мясо 333 Бакалея 444
И при общем доступе не подписывает в примечании какой юзер сделал данное изменение. А это тоже важно.koyaanisqatsi
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 Set oComment = Target.AddComment(Sheets(1).Cells(1, "b").Value & ": " & Target.Text & " " & Format(Now, "dd.mm.yy HH:MM")) Else oComment.Text oComment.Text & Chr(10) & Sheets(1).Cells(1, "b").Value & ": " & Target.Text & " " & Format(Now, "dd.mm.yy HH:MM") oComment.Shape.TextFrame.AutoSize = True 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 Set oComment = Target.AddComment(Sheets(1).Cells(1, "b").Value & ": " & Target.Text & " " & Format(Now, "dd.mm.yy HH:MM")) Else oComment.Text oComment.Text & Chr(10) & Sheets(1).Cells(1, "b").Value & ": " & Target.Text & " " & Format(Now, "dd.mm.yy HH:MM") oComment.Shape.TextFrame.AutoSize = True End If End Sub
koyaanisqatsi, думаю, что нужно определить, для начала, как будет называться лист, или какой у него будет индекс.... Я имею в виду лист, на котором Вы чистите.
koyaanisqatsi, думаю, что нужно определить, для начала, как будет называться лист, или какой у него будет индекс.... Я имею в виду лист, на котором Вы чистите.Roman777
'По всем листам For Each sh In ThisWorkbook.Sheets sh.UsedRange.ClearComments Next sh 'Только листы со 2-го по 4-й For i = 2 To 4 ThisWorkbook.Sheets(i).UsedRange.ClearComments Next i
[/vba]
koyaanisqatsi, так попробуйте [vba]
Код
'По всем листам For Each sh In ThisWorkbook.Sheets sh.UsedRange.ClearComments Next sh 'Только листы со 2-го по 4-й For i = 2 To 4 ThisWorkbook.Sheets(i).UsedRange.ClearComments Next i
SLAVICK, А этот мокрос можно заточить под то чтобы он при копипасте тоже сохранял в пометку данные из ячейку куда копипаст произведен из другой ячейки ?
[vba]
Код
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 Set oComment = Target.AddComment(Sheets(1).Cells(1, "b").Value & ": " & Target.Text & " " & Format(Now, "dd.mm.yy HH:MM")) Else oComment.Text oComment.Text & Chr(10) & Sheets(1).Cells(1, "b").Value & ": " & Target.Text & " " & Format(Now, "dd.mm.yy HH:MM") oComment.Shape.TextFrame.AutoSize = True End If End Sub
[/vba]
Во вкладке овощи заполнил несколько ячеек. История отлично работает до того момента как вставляешь через копипаст в уже заполненую ячейку. В таком случае мы видим только кто сделал запись но что было до этого пропадает.
SLAVICK, А этот мокрос можно заточить под то чтобы он при копипасте тоже сохранял в пометку данные из ячейку куда копипаст произведен из другой ячейки ?
[vba]
Код
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 Set oComment = Target.AddComment(Sheets(1).Cells(1, "b").Value & ": " & Target.Text & " " & Format(Now, "dd.mm.yy HH:MM")) Else oComment.Text oComment.Text & Chr(10) & Sheets(1).Cells(1, "b").Value & ": " & Target.Text & " " & Format(Now, "dd.mm.yy HH:MM") oComment.Shape.TextFrame.AutoSize = True End If End Sub
[/vba]
Во вкладке овощи заполнил несколько ячеек. История отлично работает до того момента как вставляешь через копипаст в уже заполненую ячейку. В таком случае мы видим только кто сделал запись но что было до этого пропадает.koyaanisqatsi
Private s$ 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 Set oComment = Target.AddComment(Sheets(1).Cells(1, "b").Value & " " & Format(Now, "dd.mm.yy HH:MM") & ":" & Chr(10) & s & "-->>" & Target.Text) Else oComment.Text oComment.Text & Chr(10) & Sheets(1).Cells(1, "b").Value & " " & Format(Now, "dd.mm.yy HH:MM") & ":" & Chr(10) & s & "-->>" & Target.Text oComment.Shape.TextFrame.AutoSize = True End If End Sub
Private Sub Worksheet_SelectionChange(ByVal Target As Range) s = Target.Cells(1, 1) End Sub
[/vba]
Так?: [vba]
Код
Private s$ 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 Set oComment = Target.AddComment(Sheets(1).Cells(1, "b").Value & " " & Format(Now, "dd.mm.yy HH:MM") & ":" & Chr(10) & s & "-->>" & Target.Text) Else oComment.Text oComment.Text & Chr(10) & Sheets(1).Cells(1, "b").Value & " " & Format(Now, "dd.mm.yy HH:MM") & ":" & Chr(10) & s & "-->>" & Target.Text oComment.Shape.TextFrame.AutoSize = True End If End Sub
Private Sub Worksheet_SelectionChange(ByVal Target As Range) s = Target.Cells(1, 1) End Sub
SLAVICK, почти. Только срабатывает один раз. Но и так лучше чем ничего. И еще одно я дико извиняюсь. А можно имя брать не из данных кто пароль ввел и из данных с какого компа сделано изменение. Я как-то сразу не заметил что вы выбрали имя того кто зашел под определенным паролем. В многопользовательском режиме есть такая функция как журнал изменений когда его нажимаешь с определенной даты он показывает кто вносил данные. И берет имя из программы экселя (общая настройка/личная настройка пользователя/имя пользователя: **** ) того компьютера с которого было это изменение внесено. Этот вариант был бы значительно предпочтительнее. Людей много кто должен вносить данные а логины и пароли хотелось бы минимализировать. Хотя я могу и каждому раздать пароль с логином.
SLAVICK, почти. Только срабатывает один раз. Но и так лучше чем ничего. И еще одно я дико извиняюсь. А можно имя брать не из данных кто пароль ввел и из данных с какого компа сделано изменение. Я как-то сразу не заметил что вы выбрали имя того кто зашел под определенным паролем. В многопользовательском режиме есть такая функция как журнал изменений когда его нажимаешь с определенной даты он показывает кто вносил данные. И берет имя из программы экселя (общая настройка/личная настройка пользователя/имя пользователя: **** ) того компьютера с которого было это изменение внесено. Этот вариант был бы значительно предпочтительнее. Людей много кто должен вносить данные а логины и пароли хотелось бы минимализировать. Хотя я могу и каждому раздать пароль с логином.koyaanisqatsi
SLAVICK, Да я понял что вы по исправлениям сделали. И история скидывается при повторном копипасте. Но это не беда. Все равно здорово.
По поводу имен. Если нажать на общий доступ к книге. То ну скажем можно будет раздать доступ человекам например 7-10 было бы логично ограничить группами доступ. Поэтому лучше выводить имя непосредственно которое забито в программе для данного человека компьютера. (общая настройка/личная настройка пользователя/имя пользователя: **** )
Если вы дадите общий доступ а потом внесете изменения и нажмете исправления вывести за сегодняшнее число и в графе кто будет указано ВСЕ то вы увидите наведя на ячейку где вносили изменение имя данное программе при установке. Оно задается тут (общая настройка/личная настройка пользователя/имя пользователя: **** )
Вот если это имя писать тогда все значительно легче становится.
Я посмотрел последний вариант почемуто у меня вообще перестало какоебыто нибыло имя выводится. У меня оффис 2010 если это важно.
А вы случайно не из виндовса пытаетесь брать имя ? Надо из программы самой Оффис 2010. Так можно ?
SLAVICK, Да я понял что вы по исправлениям сделали. И история скидывается при повторном копипасте. Но это не беда. Все равно здорово.
По поводу имен. Если нажать на общий доступ к книге. То ну скажем можно будет раздать доступ человекам например 7-10 было бы логично ограничить группами доступ. Поэтому лучше выводить имя непосредственно которое забито в программе для данного человека компьютера. (общая настройка/личная настройка пользователя/имя пользователя: **** )
Если вы дадите общий доступ а потом внесете изменения и нажмете исправления вывести за сегодняшнее число и в графе кто будет указано ВСЕ то вы увидите наведя на ячейку где вносили изменение имя данное программе при установке. Оно задается тут (общая настройка/личная настройка пользователя/имя пользователя: **** )
Вот если это имя писать тогда все значительно легче становится.
Я посмотрел последний вариант почемуто у меня вообще перестало какоебыто нибыло имя выводится. У меня оффис 2010 если это важно.
А вы случайно не из виндовса пытаетесь брать имя ? Надо из программы самой Оффис 2010. Так можно ?koyaanisqatsi
Сообщение отредактировал koyaanisqatsi - Пятница, 15.04.2016, 16:50
SLAVICK, Добрый день, а не подскажите, зачем тут [vba]
Код
Function GetUserName() 'WMI (Win32_ComputerSystem) Set objWMIService = GetObject("winmgmts:\\.\root\cimv2") Set colItems = objWMIService.ExecQuery("Select * from Win32_ComputerSystem") For Each objItem In colItems strUserName = strUserName & "|" & objItem.UserName Next GetUserName = strUserName Exit Function End Function
[/vba] строчка [vba]
Код
Exit Function
[/vba]?
SLAVICK, Добрый день, а не подскажите, зачем тут [vba]
Код
Function GetUserName() 'WMI (Win32_ComputerSystem) Set objWMIService = GetObject("winmgmts:\\.\root\cimv2") Set colItems = objWMIService.ExecQuery("Select * from Win32_ComputerSystem") For Each objItem In colItems strUserName = strUserName & "|" & objItem.UserName Next GetUserName = strUserName Exit Function End Function
Это кусок функции - просто лишнее удалил. Там были несколько вариантов вывода информации. Если интересно вот функция целиком : [vba]
Код
Function GetUserName_2(Optional t%) 'Environment Variable If t = 0 Then Set wshShell = CreateObject("WScript.Shell") strUserName = wshShell.ExpandEnvironmentStrings("%USERNAME%") GetUserName_2 = strUserName Exit Function End If 'WshNetwork If t = 1 Then Set wshNetwork = CreateObject("WScript.Network") strUserName = wshNetwork.UserName GetUserName_2 = strUserName Exit Function End If 'ADSI (WinNTSystemInfo) If t = 2 Then Set objSysInfo = CreateObject("WinNTSystemInfo") strUserName = objSysInfo.UserName GetUserName_2 = strUserName Exit Function End If 'WMI (Win32_ComputerSystem) If t = 3 Then Set objWMIService = GetObject("winmgmts:\\.\root\cimv2") Set colItems = objWMIService.ExecQuery("Select * from Win32_ComputerSystem") For Each objItem In colItems strUserName = strUserName & "|" & objItem.UserName Next GetUserName_2 = strUserName Exit Function End If End Function
Поэтому лучше выводить имя непосредственно которое забито в программе для данного человека
Попробуйте вышеприведенную функцию с разными параметрами t - что то подходит?
Это кусок функции - просто лишнее удалил. Там были несколько вариантов вывода информации. Если интересно вот функция целиком : [vba]
Код
Function GetUserName_2(Optional t%) 'Environment Variable If t = 0 Then Set wshShell = CreateObject("WScript.Shell") strUserName = wshShell.ExpandEnvironmentStrings("%USERNAME%") GetUserName_2 = strUserName Exit Function End If 'WshNetwork If t = 1 Then Set wshNetwork = CreateObject("WScript.Network") strUserName = wshNetwork.UserName GetUserName_2 = strUserName Exit Function End If 'ADSI (WinNTSystemInfo) If t = 2 Then Set objSysInfo = CreateObject("WinNTSystemInfo") strUserName = objSysInfo.UserName GetUserName_2 = strUserName Exit Function End If 'WMI (Win32_ComputerSystem) If t = 3 Then Set objWMIService = GetObject("winmgmts:\\.\root\cimv2") Set colItems = objWMIService.ExecQuery("Select * from Win32_ComputerSystem") For Each objItem In colItems strUserName = strUserName & "|" & objItem.UserName Next GetUserName_2 = strUserName Exit Function End If End Function
SLAVICK, последняя выдает пустоту все остальные выдают сетевое имя. В принципе думаю можно трансформировать сетевое имя в имя оператора компа.
На листе "Доп" выделил желтеньким сопоставление сетевых имен с именами людей. Теперь бы эту ячеку приделать к макросу который должен выдавать имя. к вот этой функции наверно [vba]
Код
strUserName
[/vba] ?
SLAVICK, последняя выдает пустоту все остальные выдают сетевое имя. В принципе думаю можно трансформировать сетевое имя в имя оператора компа.
На листе "Доп" выделил желтеньким сопоставление сетевых имен с именами людей. Теперь бы эту ячеку приделать к макросу который должен выдавать имя. к вот этой функции наверно [vba]
бы эту ячеку приделать к макросу который должен выдавать имя.
Попробуйте так:[vba]
Код
Private Sub Worksheet_Change(ByVal Target As Range) Dim oComment As Comment, un$ On Error Resume Next Set oComment = Target.Comment un = WorksheetFunction.VLookup(GetUserName_3(2), Лист4.[A2:B999], 2, False) If oComment Is Nothing Then Set oComment = Target.AddComment(un & " " & Format(Now, "dd.mm.yy HH:MM") & ":" & Chr(10) & s & "-->>" & Target.Text) oComment.Shape.TextFrame.AutoSize = True Else oComment.Text oComment.Text & Chr(10) & un & " " & Format(Now, "dd.mm.yy HH:MM") & ":" & Chr(10) & s & "-->>" & Target.Text oComment.Shape.TextFrame.AutoSize = True End If End Sub
[/vba] Только не знаю какой номер в функции Вы используете. В 1-м столбце - нужно указать имена, которые выдает функция у пользователей.
Зы если что - разговор смогу продолжить с понедельника. На даче у меня нет компа
бы эту ячеку приделать к макросу который должен выдавать имя.
Попробуйте так:[vba]
Код
Private Sub Worksheet_Change(ByVal Target As Range) Dim oComment As Comment, un$ On Error Resume Next Set oComment = Target.Comment un = WorksheetFunction.VLookup(GetUserName_3(2), Лист4.[A2:B999], 2, False) If oComment Is Nothing Then Set oComment = Target.AddComment(un & " " & Format(Now, "dd.mm.yy HH:MM") & ":" & Chr(10) & s & "-->>" & Target.Text) oComment.Shape.TextFrame.AutoSize = True Else oComment.Text oComment.Text & Chr(10) & un & " " & Format(Now, "dd.mm.yy HH:MM") & ":" & Chr(10) & s & "-->>" & Target.Text oComment.Shape.TextFrame.AutoSize = True End If End Sub
[/vba] Только не знаю какой номер в функции Вы используете. В 1-м столбце - нужно указать имена, которые выдает функция у пользователей.
Зы если что - разговор смогу продолжить с понедельника. На даче у меня нет компа SLAVICK