Как на VBA отловить удаление строки Excel?
От: Beowolf707  
Дата: 14.12.10 16:11
Оценка:
В предложенном решении, откуда надо вызывать SetCustomDelete? Добавлял в Workbook_Open, но у меня не заработало
Re: Как на VBA отловить удаление строки Excel?
От: ZAMUNDA Земля для жалоб и предложений
Дата: 15.12.10 09:21
Оценка:
Здравствуйте, Beowolf707, Вы писали:

B>В предложенном решении, откуда надо вызывать SetCustomDelete? Добавлял в Workbook_Open, но у меня не заработало

Про решение поподробнее. Версия Ёкселя?

Я б ловил Worksheet_Change а там уже ручками смарел на какой строке/столбце стоит выделение.
Наука изощряет ум; ученье вострит память.
(c) Козьма Прутков
Re[2]: Как на VBA отловить удаление строки Excel?
От: Beowolf707  
Дата: 15.12.10 14:20
Оценка:
Здравствуйте, 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Удалить
Re[3]: Как на VBA отловить удаление строки Excel?
От: ZAMUNDA Земля для жалоб и предложений
Дата: 16.12.10 01:35
Оценка:
Здравствуйте, Beowolf707, Вы писали:

Ну я, лично, сделал бы класс, который на события 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) Козьма Прутков
Re[4]: Как на VBA отловить удаление строки Excel?
От: Beowolf707  
Дата: 16.12.10 11:00
Оценка:
Здравствуйте, ZAMUNDA, Вы писали:
ThisWorkbook.Sheets(...)
Но такая форма будет требовать указания конкретного имени листа, получается под каждый лист надо писать свои события Change?
Re[5]: Как на VBA отловить удаление строки Excel?
От: ZAMUNDA Земля для жалоб и предложений
Дата: 16.12.10 15:48
Оценка:
Здравствуйте, 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) Козьма Прутков
Re[6]: Как на VBA отловить удаление строки Excel?
От: Beowolf707  
Дата: 17.12.10 21:38
Оценка:
В принципе все сделал, что хотел, осталось одно, я хочу еще сортировку делать, так вот как отличить сортировку от изменения ячеек листа?
Re[7]: Как на VBA отловить удаление строки Excel?
От: ZAMUNDA Земля для жалоб и предложений
Дата: 17.12.10 22:40
Оценка:
Здравствуйте, Beowolf707, Вы писали:

B>В принципе все сделал, что хотел, осталось одно, я хочу еще сортировку делать, так вот как отличить сортировку от изменения ячеек листа?

Если ты пишешь в ячейку дату ввода, то достаточно проверить наличие информации в целевой ячейке. Короче решай по конкретной задаче, общего решения я не знаю.
Наука изощряет ум; ученье вострит память.
(c) Козьма Прутков
Re[7]: Как на VBA отловить удаление строки Excel?
От: ZAMUNDA Земля для жалоб и предложений
Дата: 17.12.10 22:55
Оценка:
Здравствуйте, Beowolf707, Вы писали:

B>В принципе все сделал, что хотел, осталось одно, я хочу еще сортировку делать, так вот как отличить сортировку от изменения ячеек листа?

При сортировке, ни SelectionChange ни Change не срабатывает, кстати. Так что отличить-то легко, а вот поймать трудно. IMHO только отслеживанием изменений на листе, т.е. кудато сохранять список, и сравнивать с тем что есть на листе.
Наука изощряет ум; ученье вострит память.
(c) Козьма Прутков
Re[8]: Как на VBA отловить удаление строки Excel?
От: Beowolf707  
Дата: 20.12.10 00:58
Оценка:
Здравствуйте, ZAMUNDA, Вы писали:

ZAM>Здравствуйте, Beowolf707, Вы писали:


B>>В принципе все сделал, что хотел, осталось одно, я хочу еще сортировку делать, так вот как отличить сортировку от изменения ячеек листа?

ZAM>При сортировке, ни SelectionChange ни Change не срабатывает, кстати. Так что отличить-то легко, а вот поймать трудно. IMHO только отслеживанием изменений на листе, т.е. кудато сохранять список, и сравнивать с тем что есть на листе.
Действительно, оказалось что сортировка не вызывает этих событий, а значит не затрагивает моих данных.
Re[9]: Как на VBA отловить удаление строки Excel?
От: ZAMUNDA Земля для жалоб и предложений
Дата: 20.12.10 10:19
Оценка:
Здравствуйте, Beowolf707, Вы писали:

B>Действительно, оказалось что сортировка не вызывает этих событий, а значит не затрагивает моих данных.

Странно, что ты сам это посмотрел сразу!
И не забывай, что сортировать можно любой выделенный диапазон. Например, можно в твоей табличке выделить столбец с датой ввода, и отсортировать его по убыванию -- всё съедет..
Наука изощряет ум; ученье вострит память.
(c) Козьма Прутков
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.