Worksheet_Change
会触发(这就是我想要的),但是当你输入一个单元格时它也会触发,就像编辑它一样但是实际上并没有改变单元格的值(这是我不想发生什么)。
假设我想为值已更改的单元格添加阴影。所以我编码:
Private Sub Worksheet_Change(ByVal Target As Range)
Target.Interior.ColorIndex = 36
End Sub
现在测试我的工作:更改单元格A1并突出显示单元格。这是理想的行为。到现在为止还挺好。然后,双击B1但不更改其中的值,然后单击C1。你会注意到B1被突出显示!这不是理想的行为。
我是否必须完成此处讨论的捕获旧值的方法,然后在突出显示单元格之前将旧旧比较?我当然希望有一些我不知道的东西。
答案 0 :(得分:4)
我建议在另一张表格中自动维护工作表的“镜像副本”,以便与更改的单元格值进行比较。
@brettdj和@JohnLBevan基本上建议做同样的事情,但他们分别在评论或字典中存储单元格值(确实为这些想法+1)。但我的感觉是,在概念上更简单地备份单元格中的单元格,而不是其他对象(尤其是您或用户可能希望用于其他目的的注释)。所以,假设我有Sheet1
其用户可能更改的单元格。我创建了另一个名为Sheet1_Mirror
的工作表(您可以在Workbook_Open
创建,如果您愿意,可以设置为隐藏 - 由您决定)。首先,Sheet1_Mirror
的内容与Sheet1
的内容相同(同样,您可以在Workbook_Open
强制执行此操作)。
每次触发Sheet1
Worksheet_Change
时,代码都会检查Sheet1
中“已更改”单元格的值是否与Sheet1_Mirror
中的值有所不同。如果是这样,它会执行您想要的操作并更新镜像表。如果没有,那就没有了。
这应该让你走上正轨:
Private Sub Worksheet_Change(ByVal Target As Range)
Dim r As Range
For Each r In Target.Cells
'Has the value actually changed?
If r.Value <> Sheet1_Mirror.Range(r.Address).Value Then
'Yes it has. Do whatever needs to be done.
MsgBox "Value of cell " & r.Address & " was changed. " & vbCrLf _
& "Was: " & vbTab & Sheet1_Mirror.Range(r.Address).Value & vbCrLf _
& "Is now: " & vbTab & r.Value
'Mirror this new value.
Sheet1_Mirror.Range(r.Address).Value = r.Value
Else
'It hasn't really changed. Do nothing.
End If
Next
End Sub
答案 1 :(得分:2)
试试这段代码。输入范围时,它会将原始单元格值存储在字典对象中。触发工作表更改时,它会将存储的值与实际值进行比较,并突出显示所有更改 注意:提高效率参考微软脚本运行时间&amp;将 As Object 替换为 As Scripting.Dictionary ,将 CreateObject(“Scripting.Dictionary”)替换为 New Scripting.Dictionary 强>
Option Explicit
Private previousRange As Object 'reference microsoft scripting runtime & use scripting.dictionary for better performance
'I've gone with late binding to avoid references from confusing the example
Private Sub Worksheet_Change(ByVal Target As Range)
Dim cell As Variant
For Each cell In Target
If previousRange.Exists(cell.Address) Then
If previousRange.Item(cell.Address) <> cell.FormulaR1C1 Then
cell.Interior.ColorIndex = 36
End If
End If
Next
End Sub
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
Dim cell As Variant
Set previousRange = Nothing 'not really needed but I like to kill off old references
Set previousRange = CreateObject("Scripting.Dictionary")
For Each cell In Target.Cells
previousRange.Add cell.Address, cell.FormulaR1C1
Next
End Sub
PS。任何更新单元格的vba代码(即使只是颜色)都会阻止excel的撤消功能!要解决此问题,您可以重新编程撤消功能,但它可能会占用大量内存。示例解决方案:http://www.jkp-ads.com/Articles/UndoWithVBA00.asp / http://www.j-walk.com/ss/excel/tips/tip23.htm
答案 2 :(得分:2)
此代码使用“注释”来存储先前值(请注意,如果您确实需要注释用于其他目的,此方法将删除它们)
xlNone
普通模块 - 关闭评论显示
Sub SetCom()
Application.DisplayCommentIndicator = xlNoIndicator
End Sub
用于捕获更改的工作表代码
Private Sub Worksheet_Change(ByVal Target As Range)
Dim rng1 As Range
Dim shCmt As Comment
For Each rng1 In Target.Cells
If Len(rng1.Value) = 0 Then
rng1.Interior.ColorIndex = xlNone
On Error Resume Next
rng1.Comment.Delete
On Error GoTo 0
Else
On Error Resume Next
Set shCmt = rng1.Comment
On Error GoTo 0
If shCmt Is Nothing Then
Set shCmt = rng1.AddComment
shCmt.Text Text:=CStr(rng1.Value)
rng1.Interior.ColorIndex = 34
Else
If shCmt.Text <> rng1.Value Then
rng1.Interior.ColorIndex = 36
shCmt.Text Text:=CStr(rng1.Value)
End If
End If
End If
Next
End Sub
答案 3 :(得分:1)
我知道这是一个老线程,但是我有完全相同的问题“更改单元格A1并且单元格突出显示。这就是我所期望的。双击B1但不要更改那里的值然后点击C1。你会注意到B1被突出显示!“
我不想突出显示一个单元格,如果它只是双重单击而没有内部值。
我以简单的方式解决了。也许它将来有助于某人。
我刚刚在活动开始时添加了这个:
If Target.Value = "" Then
Exit Sub
End If
答案 4 :(得分:0)
我发现另一个线程提供了捕获旧值的方法,因此您可以将其与“新”值进行比较,如果是,则直接让它什么都不做。
答案 5 :(得分:-1)
您可以发送代码吗?
如果Target.Value =“”然后
退出子
万一
不能为我解决问题。