如何将我的宏更改为Worksheet_Change事件Excel VBA

时间:2018-05-15 20:10:09

标签: excel vba excel-vba

我有一个我在工作簿关闭时调用的宏。它在单独的工作表上检查两个表中的列,并根据它找到的内容分配行号。

Worksheet_Change处理程序位于具有Projects范围的工作表上。 Database范围位于同一工作簿中的另一个工作表中。

每当我在其他地方调用宏时,它会产生错误或导致excel被部分冻结的常见错误(任何人都知道这到底是什么?!?!?!)。

无论如何,我放弃之前的最后一招是将宏更改为工作表更改事件,我想知道是否可以获得一些帮助来创建它。
原始宏:

Sub FindRow()
'This module verifies row numbers in the database by matching them to the opportunities in the Projects
'worksheet. It then assigns row numbers in the Projects worksheet.

    Application.ScreenUpdating = False
    Dim LastRow As Long

    LastRow = Application.ThisWorkbook.Sheets("Projects").Cells.Find("*", SearchOrder:=xlByRows, SearchDirection:=xlPrevious).Row

    Dim rng As Range
    Dim foundRng As Range
    For Each rng In Sheets("Projects").Range("B2:B" & LastRow)
        Set foundRng = Sheets("Database").Range("C:C").Find(rng, LookIn:=xlValues, lookat:=xlWhole)
        If Not foundRng Is Nothing Then
            rng.Offset(0, -1) = foundRng.Row
        End If
    Next rng
    Application.ScreenUpdating = True
End Sub

我建议的改变:

 Public Sub Worksheet_Change(ByVal Target As Range)
     Dim Records As Range

        Set Records = Range("Records")
        If Not Application.Intersect(Records, Range(Target.Address)) Is Nothing Then
        Application.ScreenUpdating = False
        Dim LastRow As Long    
        LastRow = Application.ThisWorkbook.Sheets("Projects").Cells.Find("*", SearchOrder:=xlByRows, SearchDirection:=xlPrevious).Row

        Dim rng As Range
        Dim foundRng As Range
        For Each rng In Sheets("Projects").Range("B2:B" & LastRow)
            Set foundRng = Sheets("Database").Range("C:C").Find(rng, LookIn:=xlValues, lookat:=xlWhole)
            If Not foundRng Is Nothing Then
                rng.Offset(0, -1) = foundRng.Row
            End If
        Next rng
        Application.ScreenUpdating = True
End If
    End Sub

但是,我在定义变量LastRow的行上一直收到错误 我得到了一个应用程序定义的错误,即使之前已经正确定义了所有错误。

提前致谢。

2 个答案:

答案 0 :(得分:3)

  

Worksheet_Change个句柄位于Projects范围的工作表上。数据库范围位于同一工作簿中的另一个工作表上。 - Remi 1分钟前

这意味着rng表单上还有Projects

For Each rng In Sheets("Projects").Range("B2:B" & LastRow)

(BTW Me.Range("B2:B" & LastRow)在这里不那么模棱两可了)

您正在Worksheet_Change工作表上处理Projects事件,只要Projects工作表上的单元格值发生更改,Excel就会触发该事件。然后在该处理程序中,你这样做:

rng.Offset(0, -1) = foundRng.Row

rng工作表上的Projects是一个范围,您正在进行工作表更改的递归循环,而 可能会导致您的代码崩溃。

当您在处理工作表更改时更改工作表时,您需要告诉Excel“它没关系,我得到了这个”,阻止它每次重新触发Worksheet.Change事件:

Application.EnableEvents = False

'...code...

Application.EnableEvents = True

此外,当你切换Application.ScreenUpdating = False时,你告诉Excel“在我这么说之前不要重新粉红” - 在很多情况下可以大大加快速度,但这也意味着你需要如果发生了不好的事情,请手动将其切换回来。

您可以通过实现错误处理程序来避免这种情况 - 这是原则:

Sub DoSomething()
    On Error GoTo CleanFail
    Application.EnableEvents = False
    Application.ScreenUpdating = False

    '...code...

CleanExit:
    Application.EnableEvents = True
    Application.ScreenUpdating = True
    Exit Sub
CleanFail:
    Debug.Print Err.Description
    Stop
    Resume CleanExit
    Resume 'F8 takes you to the error-throwing statement
End Sub

答案 1 :(得分:0)

您尚未指出哪个工作表是包含worksheet_change事件的活动工作表。

无论如何,这是一个代码,用于查找B列表“Projects”

中的最后一行
    Dim LastRow As Long, sh As Worksheet

    Set sh = Sheets("Projects")

    LastRow = sh.Cells(sh.Rows.Count, "B").End(xlUp).Row
    MsgBox LastRow & " is the last row in Column B Sheet Projects!"