Здравствуйте, Beowolf707, Вы писали:
B>В предложенном решении, откуда надо вызывать SetCustomDelete? Добавлял в Workbook_Open, но у меня не заработало
Про решение поподробнее. Версия Ёкселя?
Я б ловил Worksheet_Change а там уже ручками смарел на какой строке/столбце стоит выделение.
Наука изощряет ум; ученье вострит память.
(c) Козьма Прутков
Здравствуйте, ZAMUNDA, Вы писали:
ZAM>Здравствуйте, Beowolf707, Вы писали:
B>>В предложенном решении, откуда надо вызывать SetCustomDelete? Добавлял в Workbook_Open, но у меня не заработало ZAM>Про решение поподробнее. Версия Ёкселя?
Эксель ХП ZAM>Я б ловил Worksheet_Change а там уже ручками смарел на какой строке/столбце стоит выделение.
Вообще задача у меня такая: при изменении содержимого в отдельный столбец пишется время изменения. Это я сделал, но при этом если строка была удалена, ничего делать не надо. И вот тут у меня сложности. На этом форуме нашел решение
Public LastSize As Integer
Dim DeleteFinished As Boolean
Private Sub Workbook_Open()
LastSize = ActiveSheet.UsedRange.Rows.Count
SetCustomDelete
End Sub
Private Sub Workbook_SheetActivate(ByVal Sh As Object)
LastSize = ActiveSheet.UsedRange.Rows.Count
End Sub
Private Sub Workbook_SheetChange(ByVal Sh As Object, ByVal Target As Excel.Range)
Select Case ActiveSheet.Cells(Target.Row, 1).Value
Case""If DeleteFinished = False Then
DeleteFinished = True
ActiveSheet.Cells(Target.Row, 4).Value = ""End If
Case Else
If LastSize = ActiveSheet.UsedRange.Rows.Count Then
ActiveSheet.Cells(Target.Row, 4).Value = Format(Date + Time, "dd-mm-yyyy hh:mm:ss")
End If
End Select
LastSize = ActiveSheet.UsedRange.Rows.Count
End Sub
Sub SetCustomDelete()
Dim cbc As Office.CommandBarControl
'---- Удалить из меню правого глаза мышиFor Each cbc In Application.CommandBars("Cell").Controls
If cbc.Caption = "&Удалить..."Then
cbc.OnAction = "CustomУдалить"
cbc.Tag = "CUSTOM_УДАЛИТЬ"End If
Next cbc
'---- Удалить из основного менюFor Each cbc In Application.CommandBars("Worksheet Menu Bar").Controls("Правка").Controls
If cbc.Caption = "&Удалить..."Then
cbc.OnAction = "CustomУдалить"
cbc.Tag = "CUSTOM_УДАЛИТЬ"End If
Next cbc
End Sub
Sub ResetDelete()
''' On Error Resume Next
Application.CommandBars("Cell").Reset
Application.CommandBars("Worksheet Menu Bar").Controls("Правка").Reset
On Error GoTo 0
'---- или более аккуратно в цикле удалить все с Tag = "CUSTOM_УДАЛИТЬ"End Sub
Sub CustomУдалить()
LastSize = ActiveSheet.UsedRange.Rows.Count
DeleteFinished = False
If Selection.Address = "$A$1"Then
MsgBox"Не буду удалять"Exit Sub
End If
ResetDelete
Dim cbc As Office.CommandBarControl
For Each cbc In Application.CommandBars("Cell").Controls
If cbc.Caption = "&Удалить..."Then
cbc.Execute
End If
Next cbc
SetCustomDelete
End Sub
Но тут есть некоторые проблемы, в WorkbookOpen LastSize = ActiveSheet.UsedRange.Rows.Count дает ошибку, иногда и в других местах тоже.
С заменой стандартного интерфейса тоже не все хорошо, если я делаю удаление через локальное меню — происходит удаление в обход моей процедуры, через главное — не найден макрос имя файла!CustomУдалить
Ну я, лично, сделал бы класс, который на события Change и SelectionChange листа целевого вешается и из них определяет что произошло... Правда в XL есть баг с этими событиями (Change, SelectionChange) при выполнении операций undo/redo. Если коротко, то там сложно поймать отмену вставки/удаления строки/столбца.
B>Но тут есть некоторые проблемы, в WorkbookOpen LastSize = ActiveSheet.UsedRange.Rows.Count дает ошибку, иногда и в других местах тоже.
Естессно... потомучто Active'тра-ла-ла используют только ламеры. :) Нормальные люди явно задают объекты ThisWorkbook.Sheets(...) и т.п.
B>С заменой стандартного интерфейса тоже не все хорошо, если я делаю удаление через локальное меню — происходит удаление в обход моей процедуры, через главное — не найден макрос имя файла!CustomУдалить
Потомучто полное имя писать надо: 'полное имя книги с расширением'!имя_процедуры.
Ты возьми и ручками назначь кнопке макрос, а потом посмотри какой у этой кнопки CommandBarControl.OnAction (Application.CommandBars(...).Controls(...).OnAction) прописан.
Не пользуй русские буквы в идентификаторах, особливо вперемешку с аглицкими. Запаришся разбираться в коде, и нас тут запаришь — мы тебе помогать не будем (шутка). И я знаю легенду про то как у Ёкселя взорвался электромозг от макроса на русском.
Наука изощряет ум; ученье вострит память.
(c) Козьма Прутков
Здравствуйте, ZAMUNDA, Вы писали:
ThisWorkbook.Sheets(...)
Но такая форма будет требовать указания конкретного имени листа, получается под каждый лист надо писать свои события Change?
Здравствуйте, Beowolf707, Вы писали:
B>Здравствуйте, ZAMUNDA, Вы писали: B>ThisWorkbook.Sheets(...) B>Но такая форма будет требовать указания конкретного имени листа, получается под каждый лист надо писать свои события Change?
Зачем, просто напиши класс, обработчик событий, и для каждого листа напиши по экземпляру этого класса. А можно и без класса, просто перевешивать события на активный лист.
Вот например:
'Модуль ЭтаКнига (ThisWorkBook)Option Explicit
Private WithEvents mclsWSMain As Excel.Worksheet
Private Sub mclsWSMain_Change(ByVal Target As Range)
Debug.Print"Change "; Target.AddressLocal(False, False, xlA1, True)
End Sub
Private Sub mclsWSMain_SelectionChange(ByVal Target As Range)
Debug.Print"SelectionChange "; Target.AddressLocal(False, False, xlA1, True)
End Sub
Private Sub Workbook_Deactivate()
Set mclsWSMain = Nothing
End Sub
Private Sub Workbook_Open()
Set mclsWSMain = Me.ActiveSheet
End Sub
Private Sub Workbook_SheetActivate(ByVal Sh As Object)
Set mclsWSMain = Sh
End Sub
Кстати, попробуй поудалять/повставлять строки и отменять/возвращать сделанное (Ctrl+Z, Ctrl+Y) — и посмотри что в Immediate пишется (Ctrl+G в редакторе VBA).
Наука изощряет ум; ученье вострит память.
(c) Козьма Прутков
Здравствуйте, Beowolf707, Вы писали:
B>В принципе все сделал, что хотел, осталось одно, я хочу еще сортировку делать, так вот как отличить сортировку от изменения ячеек листа?
Если ты пишешь в ячейку дату ввода, то достаточно проверить наличие информации в целевой ячейке. Короче решай по конкретной задаче, общего решения я не знаю.
Наука изощряет ум; ученье вострит память.
(c) Козьма Прутков
Здравствуйте, Beowolf707, Вы писали:
B>В принципе все сделал, что хотел, осталось одно, я хочу еще сортировку делать, так вот как отличить сортировку от изменения ячеек листа?
При сортировке, ни SelectionChange ни Change не срабатывает, кстати. Так что отличить-то легко, а вот поймать трудно. IMHO только отслеживанием изменений на листе, т.е. кудато сохранять список, и сравнивать с тем что есть на листе.
Наука изощряет ум; ученье вострит память.
(c) Козьма Прутков
Здравствуйте, ZAMUNDA, Вы писали:
ZAM>Здравствуйте, Beowolf707, Вы писали:
B>>В принципе все сделал, что хотел, осталось одно, я хочу еще сортировку делать, так вот как отличить сортировку от изменения ячеек листа? ZAM>При сортировке, ни SelectionChange ни Change не срабатывает, кстати. Так что отличить-то легко, а вот поймать трудно. IMHO только отслеживанием изменений на листе, т.е. кудато сохранять список, и сравнивать с тем что есть на листе.
Действительно, оказалось что сортировка не вызывает этих событий, а значит не затрагивает моих данных.
Здравствуйте, Beowolf707, Вы писали:
B>Действительно, оказалось что сортировка не вызывает этих событий, а значит не затрагивает моих данных.
Странно, что ты сам это посмотрел сразу!
И не забывай, что сортировать можно любой выделенный диапазон. Например, можно в твоей табличке выделить столбец с датой ввода, и отсортировать его по убыванию -- всё съедет..
Наука изощряет ум; ученье вострит память.
(c) Козьма Прутков