Excel VBA事件处理程序

1)有人可以告诉我这个代码可能是什么问题?

2)我需要这个代码实际上运行在工作表更新,但@首次加载的工作簿,我运行更新使用Workbook_Open事件处理程序。 这不会触发我的Worksheet_Change事件吗? 有什么办法可以避免这种情况吗?

 Private Sub Worksheet_Change(ByVal Target As Range) Dim ws As Worksheet Dim rowCount As Integer Set Worksheet = "datasheet" Set rowCount = ws.Cells(Rows.Count, "A").End(xlUp) If Not Intersect(Target, Range("M3:M" & CStr(rowCount))) Is Nothing Then MsgBox ("Hi") End If Else If Not Intersect(Target, Range("T3:T" & CStr(rowCount))) Is Nothing Then MsgBox ("Hi") End If Else If Not Intersect(Target, Range("X3:X" & CStr(rowCount))) Is Nothing Then MsgBox ("Hi") End If Else If Not Intersect(Target, Range("AB3:AB" & CStr(rowCount))) Is Nothing Then MsgBox ("Hi") End If Else If Not Intersect(Target, Range("AI3:AI" & CStr(rowCount))) Is Nothing Then MsgBox ("Hi") End If End Sub 

我得到一个编译器错误,说“对象需要”,当我用这个处理程序更改我的数据。 另一方面,如果我给的价值,而不是采取行数,我没有问题。

我总是build议使用Worksheet_Change

  1. 您不需要工作表名称。 据了解,代码将在当前工作表上运行,除非您正在尝试使用另一个工作表行作为参考,正如下面的注释中由brettdj正确提到的那样。

  2. 每当您使用Worksheet_Change事件。 如果要将数据写入单元,请始终closures事件。 这是必需的,以便代码不会进入可能的无限循环

  3. 无论何时closures事件,如果出现错误,请使用error handling,否则代码将不会在下一次运行。

这是一个例子

 Option Explicit Private Sub Worksheet_Change(ByVal Target As Range) On Error GoTo Whoa Application.EnableEvents = False ' '~~> Rest of the code ' LetsContinue: Application.EnableEvents = True Exit Sub Whoa: MsgBox Err.Description Resume LetsContinue End Sub 

所以使用上面的代码变成(UNTESTED)

 Private Sub Worksheet_Change(ByVal Target As Range) Dim rowCount As Long On Error GoTo Whoa Application.EnableEvents = False With ActiveSheet rowCount = .Cells(.Rows.Count, "A").End(xlUp).Row End With If Not Intersect(Target, Range("M3:M" & rowCount)) Is Nothing Then MsgBox ("Hi") ElseIf Not Intersect(Target, Range("T3:T" & rowCount)) Is Nothing Then MsgBox ("Hi") ElseIf Not Intersect(Target, Range("X3:X" & rowCount)) Is Nothing Then MsgBox ("Hi") ElseIf Not Intersect(Target, Range("AB3:AB" & rowCount)) Is Nothing Then MsgBox ("Hi") ElseIf Not Intersect(Target, Range("AI3:AI" & rowCount)) Is Nothing Then MsgBox ("Hi") End If LetsContinue: Application.EnableEvents = True Exit Sub Whoa: MsgBox Err.Description Resume LetsContinue End Sub 

编辑

关于你的第二个问题。 正如我在上面的评论中所提到的,您可以使用Publicvariables来检查工作表更改事件是否由打开的工作簿引起。

将此代码放在一个模块中。

 Public WasWbOpened As Boolean 

将此代码放在工作簿代码区域中

 Option Explicit Private Sub Workbook_Open() WasWbOpened = True ' '~~> Rest of the code ' WasWbOpened = False End Sub 

并将您的工作表更改事件更改为

 Private Sub Worksheet_Change(ByVal Target As Range) If WasWbOpened = True Then Exit Sub Dim rowCount As Long On Error GoTo Whoa Application.EnableEvents = False With ActiveSheet rowCount = .Cells(.Rows.Count, "A").End(xlUp).Row End With If Not Intersect(Target, Range("M3:M" & rowCount)) Is Nothing Then MsgBox ("Hi") ElseIf Not Intersect(Target, Range("T3:T" & rowCount)) Is Nothing Then MsgBox ("Hi") ElseIf Not Intersect(Target, Range("X3:X" & rowCount)) Is Nothing Then MsgBox ("Hi") ElseIf Not Intersect(Target, Range("AB3:AB" & rowCount)) Is Nothing Then MsgBox ("Hi") ElseIf Not Intersect(Target, Range("AI3:AI" & rowCount)) Is Nothing Then MsgBox ("Hi") End If LetsContinue: Application.EnableEvents = True Exit Sub Whoa: MsgBox Err.Description Resume LetsContinue End Sub 

你有几个问题

  1. 根据Sid的评论,你应该使用rowCount = ws.Cells(ws.Rows.Count, "A").End(xlUp).Row
  2. 你应该使用Set ws = Sheets("datasheet")而不是Set Worksheet = "datasheet"
  3. 您的Else陈述在成为孤儿时造成错误。 如果你想退出第一个“嗨”,而不是继续testing你应该尝试这样的事情

希德已经涵盖了你的另一点。 你可以使用一个Booleanvariables

更新的代码

这将在单行中testing从第3行到第row行的列M,T,X,AB和AI上的相交

 Private Sub Worksheet_Change(ByVal Target As Range) Dim ws As Worksheet Dim rowCount As Long Set ws = Sheets("datasheet") rowCount = ws.Cells(Rows.Count, "A").End(xlUp).Row If Not Intersect(Target, Range("M3:M" & CStr(rowCount) & ",T3:T" & CStr(rowCount) & ",X3:X" & CStr(rowCount) & ",AB3:AB" & CStr(rowCount) & ",AI3:AI" & CStr(rowCount))) Is Nothing Then MsgBox ("Hi") End Sub