2017-09-05 66 views
3

我是一个Excel-VBA新手,我正在尝试编写一段代码,该代码由某人更改工作表中单元格的值触发。它应该将更改单元格的值设置为零,如果它小于零。代码如下所示:Worksheet_Change事件中的目标范围不正确

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事件处理程序创建的“目标”对象只包含更改的单元/单元,因此我的代码只会更改被修改的单元格的值,并触发第一名。

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

实际上我发现了一个问题本身的解决方法,但我的问题是这样的:我如何在使用Worksheet_Change事件失败以及未来可以做什么以避免出现这样的问题?

+2

使用application.enableevents = false或您的事件过程将自行运行。 – Jeeped

+0

'Target'确实只涉及已更改的单元格,并且我无法复制您的错误。试试Jeeped的修正案,看看你如何继续。 – SJR

+1

不要忘记将它设置回'Application.EnableEvents = True',否则你的事件将不会在下次启动 – Tom

回答

0

编辑1:与bug修复更新代码中的注释

编辑2提示:更新代码错误处理,处理数组公式

在回答你的问题

[1]我怎么在使用Worksheet_Change事件和[2]我可以在未来做些什么不会有这样的问题?

  1. 技术上你没有
  2. 没有这种类型的问题,尽管以下规则一般

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

的原因,你的Debug.Print显示所有单元格的是,每次你的代码更改单元格,另一变化事件被触发。幸运的是第二个发现一个零,所以它不会触发另一个之一。下面的一般规则应该有助于避免了很多问题,只是没有这个特殊的一个:

  • 始终围绕在改变与Application.EnableEvents工作簿中的任何一部分的事件处理程序的任何代码。

要修复你的代码,所以它可以工作,只需删除SpecialCells方法调用。由于您使用的是Cell.Value而不是强烈推荐的Cell.Value2(请参阅here),VBA隐式类型会将格式为文本的数字转换为实际的数字。因此,该代码对数字和文本值都起作用。

代码:

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应对进入数组公式。它可以允许在列6中输入数组公式,以便在列6中输入负值,或者完全停止输入。

+0

我避免使用target.column,因为可以使用Ctrl + Enter在水平范围内输入数据。 –

+0

@PatrickHonorez不知道我明白。您也可以在*垂直*范围内输入数据。公式必须不同。 – robinCTS

+0

'Target'可能是一个范围,并且覆盖了几列。因此'如果Target.Column = 6'容易出错。 –

0

此作品(更新

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

+0

我无法使用'.SpecialCells(xlCellTypeConstants,3)' – Tom

+0

这也适用于3。它不包括在[文档](https://msdn.microsoft.com/en-us/vba/excel-vba/articles/range-specialcells-method-excel) – Tom

+1

@Tom:根据文档3等于'xlNumbers + xlTextValues'。这个工程,我只是试过 –