Worksheet_Change事件中的目标范围不正确

我是一个Excel-VBA新手,我想写一小段代码,这个代码是由某个人在工作表中改变单元格的值而触发的。 如果小于零,它应该将更改的单元格的值设置为零。 代码如下所示:

Private Sub Worksheet_Change(ByVal Target As Range) 'Debug.Print Target.Address If Target.Column = 6 Then For Each Cell In Target.SpecialCells(xlCellTypeConstants, 3) If Cell.Value < 0 Then Cell.Value = 0 End If Next End If End Sub 

现在发生的是,当我改变列6中的任何单元格的值时,包含小于零的数字的表单中的每个单元格也都变为零。

我在想为Worksheet_Change事件处理程序创build的“Target”对象只包含已更改的单元格/单元,因此我的代码只会更改已修改并触发事件的单元格的值。

我试图通过使用Debug.Print输出对象的地址来帮助自己。 它打印出的值小于零的表格中的每个单元格的地址,所以我假设处理程序跑了好几次。

实际上,我发现问题本身的一个解决方法,但我的问题是这样的:我怎么在使用Worksheet_Change事件失败,我可以做什么在未来没有这样的问题?

编辑1:更新的代码与错误修复build议在评论中

编辑2:更新error handling代码来处理数组公式

回答你的问题

[1]我如何在使用Worksheet_Change事件失败,以及[2]我今后可以做什么没有这样的问题?

  1. 从技术上讲,你没有
  2. 这种types的问题没有什么,尽pipe下面的规则总体上有帮助

你对Target对象的理解是正确的。 您的代码失败,因为SpecialCells不喜欢单个单元格操作。 给它一个,它扩大到整个表! 给别的,它工作得很好。

Debug.Print显示所有单元格的原因是,每当您的代码更改单元格时,都会触发另一个更改事件。 幸运的是,第二个find一个零,所以它不会触发另一个 。 下面的一般规则应该有助于避免很多问题,而不是这个问题:

  • 始终围绕事件处理程序中的任何代码,用Application.EnableEvents更改工作簿的任何部分

要解决你的代码,所以它的工作,只需删除SpecialCells方法调用。 由于您使用的是Cell.Value而不是强烈推荐的Cell.Value2 (请参见此处 ),VBA隐式types可将数字格式化为实际数字。 因此,代码可以同时处理数字和文本值。

码:

 Private Sub Worksheet_Change(ByVal Target As Range) 'Debug.Print Target.Address; Application.EnableEvents = False For Each Cell In Target '.SpecialCells(xlCellTypeConstants, 3) If Cell.Column = 6 And Cell.Value < 0 Then On Error GoTo Error: Cell.Value = 0 On Error GoTo 0 End If Next GoTo ExitSub: Error: If Err.Number = 1004 Then ' 1004 -> "You cannot change part of an array." 'Application.Undo ' Uncomment to disallow array entering a negative value formula into/across column 6 MsgBox "A cell could not be zeroed as" & vbCr & "it is part of an array formula.", vbExclamation, "Microsoft Office Excel" On Error GoTo 0 Else On Error GoTo 0 Resume End If ExitSub: Application.EnableEvents = True End Sub 

笔记:

– 更新1:代码现在正确地处理多单元格更改。

– 更新2:代码现在陷阱错误1004来处理input数组公式。 它可以允许在列6中input数组公式,而在列6中input负数,或者完全停止input。

这工作( 更新

 Private Sub Worksheet_Change(ByVal Target As Range) Dim c As Range For Each c In Target If c.Column = 6 Then If IsNumeric(c) Then If c < 0 Then c = 0 Next c End Sub 

请学习和使用OPTION EXPLICIT