Как перехватить новые добавления строк в списке? - PullRequest
4 голосов
/ 28 декабря 2011

Я хочу выполнять обработчик событий VBA на листе Excel 10 всякий раз, когда пользователь добавляет новую строку в список (вид списков, которые Worksheet.ListObjects () возвращает экземпляры) на этом листе, например, путем ввода данных под последней строкой списка (это расширяет список, добавляя новую строку в список).

Как мне это сделать? Помимо прочего, я хочу установить значения по умолчанию для определенных ячеек новой строки.

Моя текущая идея - обработать Worksheet_Change и проверить, находится ли параметр Target в пределах .Range ListObject, в котором я заинтересован.

Однако, как бы я узнал, создает ли пользователь новую строку с изменением его / ее ячейки, и дифференцировал бы ее от изменений существующих ячеек в списке?

Я, наверное, просто немного глупый здесь. Я ожидал, что будет событие списка, которое я смогу перехватить, но я не могу найти ни одного.

1 Ответ

3 голосов
/ 30 декабря 2011

Я думаю, что вы правы, для ListObject событий нет. Использование Worksheet_Change кажется правильным решением. Чтобы обнаружить редактирование New Row vs Existing Row, вам нужно будет применить свой собственный метод.

Я бы предложил отслеживать количество строк в ListOjects, чтобы определить, когда они изменяются. Чтобы сделать это, попробуйте добавить скрытый named range для каждого ListOject, чтобы сохранить текущее количество строк. Заполните их при открытии файла и проверьте их на Worksheet_Change.

Это добавит или обновит скрытые именованные диапазоны при открытии файла (добавить в модуль Workbook)

Private Sub Workbook_Open()
    Dim oList As ListObject
    Dim sh As Worksheet
    Dim nm As Name
    Dim strName As String

    For Each sh In Me.Worksheets
    For Each oList In sh.ListObjects
        'oList.ListRows.Count
        strName = oList.Name & "Rows"
        Set nm = Nothing
        On Error Resume Next
        Set nm = Me.Names(strName)
        On Error GoTo 0
        If nm Is Nothing Then
            Set nm = Me.Names.Add(strName, CStr(oList.ListRows.Count))
        Else
            nm.RefersTo = CStr(oList.ListRows.Count)
        End If
        nm.Visible = False
    Next oList, sh
End Sub

Это определит тип изменений. Я сделал это событие уровня WorkBook, поэтому для всех листов требуется только одно. (добавить в модуль Workbook)

Private Sub Workbook_SheetChange(ByVal sh As Object, ByVal Target As Range)
    Dim oList As ListObject
    Dim nm As Name
    Dim strName As String

    For Each oList In sh.ListObjects
        strName = oList.Name & "Rows"
        If Not Application.Intersect(Target, oList.DataBodyRange) Is Nothing Then
            Set nm = Nothing
            On Error Resume Next
            Set nm = Me.Names(strName)
            On Error GoTo 0
            If nm Is Nothing Then
                Set nm = Me.Names.Add(strName, CStr(oList.ListRows.Count))
                nm.Visible = False
            End If
            If oList.ListRows.Count <> Val(Replace(nm.Value, "=", "")) Then
                nm.RefersTo = CStr(oList.ListRows.Count)
                MsgBox "List " & oList.Name & " changed" & vbCrLf & "New Line"
            Else
                MsgBox "List " & oList.Name & " changed" & vbCrLf & "Existing Line"
            End If
        End If
    Next
End Sub

Примечание. Это не относится к случаю, когда имя существующего объекта ListObject изменяется. Это оставлено в качестве упражнения для читателя

...