Excel:范围内的先前值
Excel: Previous Values from Ranges
我想在复制单个单元格并将其粘贴到多个单元格时获取以前的单元格值。 How can I determine new & previous cell value on SheetChange event in Excel? 足以检测单个单元格的先前值。但是,当我尝试复制一个单元格(ctrl+v、拖动等)并将其应用于多个单元格时,检测到先前值的 none。相反,值数组等于第一个单元格,这使我得出结论,单元格在 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
}
}
恐怕要实现监控所有 sheet 个细胞的目标,您必须:
制作一个 "mirror" 整个副本 "base" sheet
其中的每个单元格将引用 "base" sheet 中的相应单元格(即 "mirror" sheet A1 单元格将具有“="baseSheetName!A1"公式”,等等)
在 "base" sheet 中进行任何更改之前设置 Application.Calculation = xlCalculationManual
(可能在工作簿打开时将其设置为默认配置)
使用 Worksheet_SelectionChange() 事件处理程序的 Target
参数到 select 相应的 "Mirror" sheet 单元格,感谢 Application.Calculation = xlCalculationManual
设置,将仍然有以前的值
如果您担心 "base" sheet 个单元格的数量有限,您可以以类似的方式继续,但将 "mirror" 个单元格保留在 "base" sheet本身
在后一种情况下,这里有一个代码来处理它(注意:VBA 代码,但您可以轻松地用 C# 翻译”)
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" sheet 中设置一个命名范围(我称之为 "sensitiveRange"),其中的所有单元格都必须被跟踪
您可以在 运行 Undo
之前获取选择,并在过程结束时恢复它。
注意:如果 sheet 未激活(例如,在 sheet 被代码更新的情况下),最后的 Select 将失败,因此您可能需要检查一下。
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
我想在复制单个单元格并将其粘贴到多个单元格时获取以前的单元格值。 How can I determine new & previous cell value on SheetChange event in Excel? 足以检测单个单元格的先前值。但是,当我尝试复制一个单元格(ctrl+v、拖动等)并将其应用于多个单元格时,检测到先前值的 none。相反,值数组等于第一个单元格,这使我得出结论,单元格在 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
}
}
恐怕要实现监控所有 sheet 个细胞的目标,您必须:
制作一个 "mirror" 整个副本 "base" sheet
其中的每个单元格将引用 "base" sheet 中的相应单元格(即 "mirror" sheet A1 单元格将具有“="baseSheetName!A1"公式”,等等)
在 "base" sheet 中进行任何更改之前设置
Application.Calculation = xlCalculationManual
(可能在工作簿打开时将其设置为默认配置)使用 Worksheet_SelectionChange() 事件处理程序的
Target
参数到 select 相应的 "Mirror" sheet 单元格,感谢Application.Calculation = xlCalculationManual
设置,将仍然有以前的值
如果您担心 "base" sheet 个单元格的数量有限,您可以以类似的方式继续,但将 "mirror" 个单元格保留在 "base" sheet本身
在后一种情况下,这里有一个代码来处理它(注意:VBA 代码,但您可以轻松地用 C# 翻译”)
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" sheet 中设置一个命名范围(我称之为 "sensitiveRange"),其中的所有单元格都必须被跟踪
您可以在 运行 Undo
之前获取选择,并在过程结束时恢复它。
注意:如果 sheet 未激活(例如,在 sheet 被代码更新的情况下),最后的 Select 将失败,因此您可能需要检查一下。
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