如何将宏更改为工作表\u更改事件Excel VBA

如何将宏更改为工作表\u更改事件Excel VBA,vba,excel,Vba,Excel,我有一个在工作簿关闭时调用的宏。它检查单独工作表上两个表中的列,并根据找到的内容指定行号 工作表\u Change处理程序位于具有项目范围的工作表上数据库范围位于同一工作簿中的另一个工作表上。 每当我在其他地方调用宏时,它要么生成错误,要么导致excel部分冻结的常见错误(谁知道这到底是什么?!) 无论如何,在放弃之前,我的最后一个办法是将宏更改为工作表更改事件,我想知道是否可以获得一些帮助来创建它。 原始宏: Sub FindRow() 'This module verifies row nu

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

工作表\u Change
处理程序位于具有
项目范围的工作表上<代码>数据库
范围位于同一工作簿中的另一个工作表上。

每当我在其他地方调用宏时,它要么生成错误,要么导致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
的行中不断遇到错误
我得到一个应用程序定义的错误,即使之前所有的东西都定义正确


提前感谢。

您尚未指明哪个工作表是具有工作表更改事件的活动工作表

无论如何,这里有一个代码来查找B列工作表“项目”中的最后一行

工作表\u Change
句柄位于具有
项目范围的工作表上。数据库范围位于同一工作簿中的另一个工作表上雷米1分钟前

这意味着
rng
也在
Projects
表中:

For Each rng In Sheets("Projects").Range("B2:B" & LastRow)
(顺便说一句,
Me.Range(“B2:B”和LastRow)
在这里就不会那么模棱两可了)

您正在处理
Projects
工作表上的
工作表\u Change
事件,每当
Projects
工作表上的单元格值发生更改时,Excel就会触发该事件。然后在该处理程序中,执行以下操作:

rng.Offset(0, -1) = foundRng.Row
由于
rng
Projects
工作表上的一个范围,您正在进入一个工作表更改的递归周期,这很可能是导致代码崩溃的原因

当您在处理工作表更改时进行工作表更改时,您需要通过防止Excel重新触发
工作表来告诉Excel“没关系,我知道了”,每次:

Application.EnableEvents = False

'...code...

Application.EnableEvents = True
此外,当您切换
Application.screenUpdate=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

你做过调试吗?lastrow的价值是什么?@SJR调试什么都没有,因为它不喜欢这行代码,所以根本不需要运行它。当它在独立模块中作为宏运行时,它确实会给我正确的行,这是表的最后一行。。。有没有可能解决您的问题?@Remi您被要求澄清涉及哪些工作表,并提供一个简单的示例。你知道为什么会这样问吗?找出代码不起作用的原因。因此,如果你不想提供这些,如果问题解决了,不要感到惊讶“奇怪的是,在它导致错误后,我无法在工作簿中的任何工作表上选择任何单元格,即使在我结束宏之后也是如此。我必须关闭工作簿并重新打开它才能再次使用它。这就像它试图崩溃,然后忘记了它或其他东西。”-这是因为你有
应用程序。屏幕更新
设置为
。在即时窗格中键入
应用程序。屏幕更新=真
(Ctrl+G)然后一切都会恢复正常。Excel不会重新绘制自己,因为您明确告诉它不要这样做。包含
记录范围的工作表是活动工作表。但这不是问题所在。问题是行
LastRow=ThisWorkbook.Sheets(“Projects”).Cells.Find(“*,SearchOrder:=xlByRows,SearchDirection:=xlPrevious)。行
在一个版本的代码中正常,但在另一个版本中不起作用。@Remi
Set Records=[Me.]Range(“Records”)
已经说明了这一点。我们仍然不知道的是
工作表(“项目”)
是否为同一工作表。@MathieuGuindon它检查单独工作表上两个表中的列,并根据找到的内容分配行号。我在操作中说过。项目在另一个工作表中。@Remi好的,最后一次:具体地说,这个
工作表\u Change
处理程序是用哪个工作表编写的?与您似乎暗示的相反,“另一个工作表”不清楚。@MathieuGuindon
工作表\u Change
句柄位于范围为
项目的工作表上<代码>数据库
范围位于同一工作簿中的另一个工作表上。它工作正常!我添加了您建议的
On Error GoTo
CleanExit
CleanFail
行代码,它可以正常工作!而且没有错误。我不知道它为什么有效,但谢谢你!
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