检测是否通过编辑实际更改了单元格值

当单元格值被改变(这是我想要的)时, Worksheet_Change会触发,但是当你input一个单元格的时候,它也会触发,就像编辑它一样,但是实际上并没有改变单元格的值(这就是我不想要的发生)。

说我想添加阴影的价值改变的单元格。 所以我编码:

 Private Sub Worksheet_Change(ByVal Target As Range) Target.Interior.ColorIndex = 36 End Sub 

现在来testing我的工作:更改单元格A1,单元格突出显示。 这是所需的行为。 到现在为止还挺好。 然后,双击B1,但不要更改那里的值,然后单击C1。 你会注意到B1被突出显示! 而这不是理想的行为。

我是否必须通过这里讨论的捕获旧值的方法,然后在突出显示单元格之前比较旧的和新的? 我当然希望有一些我错过了。

我build议在另一张表中自动维护你的工作表的“镜像副本”,以便与更改的单元格的值进行比较。

@brettdj和@JohnLBevan本质上是build议做同样的事情,但是它们分别在注释或字典中存储单元格值(实际上对这些概念也是+1)。 然而,我的感觉是,在单元格而不是其他对象(特别是您或用户可能希望用于其他目的的注释)中备份单元格在概念上要简单得多。

所以说,我有Sheet1的单元格的用户可能会改变。 我创build了另一个名为Sheet1_Mirror Workbook_Open表(您可以在Workbook_Open创build该Workbook_Open并且可以设置为隐藏,如果您愿意的话 – 取决于您)。 首先, Sheet1_Mirror的内容将与Sheet1的内容相同(同样,您可以在Workbook_Open执行此操作)。

每次触发Sheet1Worksheet_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. 没有值的单元格将颜色重置为xlNone
  2. input到单元格中的初始值是蓝色(ColorIndex 34)
  3. 如果值更改,则单元格将从蓝色变为黄色

在这里输入图像说明

正常模块 – closures评论的显示

  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 

试试这个代码。 当您input范围时,它将原始单元格值存储在字典对象中。 当工作表更改被触发时,它将存储的值与实际值进行比较,并突出显示所有更改。
注意:为了提高效率,请参考Microsoft脚本运行时,并用New Scripting.DictionaryreplaceAs Object 作为Scripting.DictionaryCreateObject(“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的撤消function工作! 为了解决这个问题,你可以重新编程撤消function,但是它可能会占用相当多的内存。 示例解决scheme: http : //www.jkp-ads.com/Articles/UndoWithVBA00.asp / http://www.j-walk.com/ss/excel/tips/tip23.htm

我知道这是一个旧的线程,但我有这样的问题完全一样“更改单元格A1和单元格突出显示,这是我所期望的。双击B1,但不要更改那里的值,然后单击C1。你会注意到B1被突出显示!“

我不想突出显示一个单元格,如果它只是双击没有价值的内部。

我用简单的方法解决了。 也许这对未来有帮助。

我刚刚在活动的开始时join了这个:

  If Target.Value = "" Then Exit Sub End If