繁体   English   中英

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

[英]Incorrect target range in Worksheet_Change event

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

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

我实际上找到了问题本身的解决方法,但我的问题是:我如何使用Worksheet_Change事件失败,以及我将来可以做些什么来解决这些问题呢?

这工作( 更新

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

编辑1:更新了代码,并在评论中提供了错误修复

编辑2:更新了具有错误处理的代码以处理数组公式

回答你的问题

[1]我是如何使用Worksheet_Change事件失败的,以及[2]我将来怎么办才能没有这样的问题?

  1. 从技术上讲,你没有
  2. 这类问题没什么,尽管以下规则有助于解决这个问题

您对Target对象的理解是正确的。 您的代码失败,因为SpecialCells不喜欢单个单元格进行操作。 给它一个,它将它扩展到整个工作表! 给它任何其他东西,它工作得很好。

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

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

要修复代码以使其正常工作,只需删除SpecialCells方法调用即可。 由于您使用的是Cell.Value而不是强烈推荐的Cell.Value2 (请参见此处 ),因此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列中产生负值,或者完全停止输入。

我来到这里寻找一种方法来阻止我的工作表“闪烁”,因为它运行代码来格式化列和行,因为用户在工作表中的任何位置更改数据,包括过滤器和排序。

除此之外,从官方答案OP的问题,如果你试图控制Worksheet_Change()根本上(仍然会闪光,但你可以绕过它)发射,在你希望用户更改例如数据的情况下事件,但不是数据周围的区域,例如作为VBA系统一部分的字段或标签,我使用Target.Row元素来确定我的限制。 结合Target.Column ,您可以磨练用户可以自由控制的特定单元格。

Dim myTopLimit AS Integer
myTopLimit = 6
etc..etc
if Target.Row < myTopLimit and Target.Row > myBottomLimit and Target.Column < myLeftLimit and Target.Column > myRightLimit then
.... code to allow WorkSheet_Change() to do somthing
else
.... code to force WorkSheet_Change() to drop through or no code
End If

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM