Excel:范围的先前值

时间:2016-02-29 06:50:14

标签: excel vba excel-vba vsto

我希望在复制单个单元格并将其粘贴到多个单元格时获取以前的单元格值。 How can I determine new & previous cell value on SheetChange event in Excel?足以检测单个单元格的先前值。但是,当我尝试复制一个单元格(ctrl + v,拖动等)并将其应用于多个单元格时,未检测到任何先前的值。相反,值数组等于第一个单元格,这使我得出结论,在SheetSelectionChange事件发生之前单元格已更改。知道如何处理这个吗?

private void Application_SheetSelectionChange(object Sh, Excel.Range Target)
    {
        try
        {
            if (Target.Value2 != null)
            {
                foreach (Excel.Range range in Target)
                {
                   // Each range in Target has same value as first value instead of previous value
                }
            }
        }
        catch (Exception ex)
        {
           // Log stuff
        }
    }

2 个答案:

答案 0 :(得分:1)

我害怕实现你的目标,监控所有的单元格:

  • 制作"镜像"整个" base"的副本片

    每个单元格将引用" base"中的相应单元格。表格(即"镜像"表格A1单元格将具有" =" baseSheetName!A1"公式"等等)

  • 在更改" base"之前设置Application.Calculation = xlCalculationManual工作表(可能在工作簿开头时将其设置为工作簿的默认配置)

  • 使用Worksheet_SelectionChange()事件处理程序的Target参数来选择相应的"镜像"由于Application.Calculation = xlCalculationManual设置,表单单元格仍具有上一个值

如果你关注的是数量有限的" base"单元格,你可以以类似的方式继续,但保持"镜像" " base"中的细胞表单本身

在后一种情况下,这里有一个处理它的代码(注意:VBA代码,但您可以轻松地在C#和#34中翻译;)

Private Sub Worksheet_SelectionChange(ByVal Target As Range)
Dim sensitiveRange As Range
Dim sensitiveRangeSelected As Range

Set sensitiveRange = Range("sensitiveRange")
Set sensitiveRangeSelected = Application.Intersect(sensitiveRange, Target)
If sensitiveRangeSelected Is Nothing Then
    ' no 'sensitive' cells  --> go ahead
Else
    ' 'sensitive' cells !! -> add code to handle thier value or store it in some array
End If

End Sub

你必须在你的" base"中设置一个命名范围(我称之为" sensitiveRange")包含必须跟踪的所有单元格的工作表

答案 1 :(得分:1)

您可以在运行Undo之前获取所选内容,并在流程结束时将其恢复。

注意:如果工作表未处于活动状态(如果工作表正在按代码更新),则最后的选择将失败,因此您可能需要检查该工作表。

Private Sub Worksheet_Change(ByVal Target As Range)

    Dim Where As String, OldValue As Variant, NewValue As Variant
    Dim r As Long, c As Long, tmp
    Dim sel As Object '<<< current selection: not always a Range!
    Dim rngTrack As Range

    On Error GoTo haveError
    Application.EnableEvents = False
    Set sel = Selection '<<< capture the selection
    Where = Target.Address
    NewValue = Target.Value
    Application.Undo
    OldValue = Target.Value 'get the previous values
    Target.Value = NewValue
    Application.EnableEvents = True

    Set rngTrack = Sheets("Tracking").Cells(Rows.Count, 1).End(xlUp).Offset(1, 0)

    'set some limit for the size of change you want to track
    If Target.Cells.CountLarge < 1000 Then

        'convert single-cell values to array...
        If Target.Cells.CountLarge = 1 Then
            OldValue = ToArray(OldValue)
            NewValue = ToArray(NewValue)
        End If

        'multi-cell: treat as arrays
        For r = 1 To UBound(OldValue, 1)
        For c = 1 To UBound(OldValue, 2)
            If OldValue(r, c) <> NewValue(r, c) Then
                rngTrack.Resize(1, 3).Value = _
                  Array(Target.Cells(r, c).Address, OldValue(r, c), NewValue(r, c))
                Set rngTrack = rngTrack.Offset(1, 0)
            End If
        Next c
        Next r
    End If

    sel.Select '<<< reset the selection
    Exit Sub

haveError:
    Application.EnableEvents = True

End Sub
'utility function
Private Function ToArray(v)
    Dim rv(1 To 1, 1 To 1)
    rv(1, 1) = v
    ToArray = rv
End Function