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
-
您不需要工作表名称。 据了解,代码将在当前工作表上运行,除非您正在尝试使用另一个工作表行作为参考,正如下面的注释中由brettdj正确提到的那样。
-
每当您使用
Worksheet_Change
事件。 如果要将数据写入单元,请始终closures事件。 这是必需的,以便代码不会进入可能的无限循环 -
无论何时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
你有几个问题
- 根据Sid的评论,你应该使用
rowCount = ws.Cells(ws.Rows.Count, "A").End(xlUp).Row
- 你应该使用
Set ws = Sheets("datasheet")
而不是Set Worksheet = "datasheet"
- 您的
Else
陈述在成为孤儿时造成错误。 如果你想退出第一个“嗨”,而不是继续testing你应该尝试这样的事情
希德已经涵盖了你的另一点。 你可以使用一个Boolean
variables
更新的代码
这将在单行中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