有可能是一个更好的方式来做到这一点,但这是来到我的脑海:
In Profile Sheet Module
Option Explicit
Public dArr As Variant
Private Sub Worksheet_Calculate()
Dim nArr As Variant
Dim auditRecord As Range
Dim i As Long
Dim j As Long
nArr = Me.UsedRange
'Look for changes to the used range
For i = 1 To UBound(dArr, 2)
For j = 1 To UBound(dArr, 1)
If nArr(j, i) <> dArr(j, i) Then
'write to range
If Not Write_Change(dArr(j, i), nArr(j, i), Me.Cells(j, i).Address) Then
MsgBox "The change was not recorded.", vbInformation
End If
End If
Next j
Next i
Erase nArr, dArr
dArr = Me.UsedRange
End Sub
Private Sub Worksheet_Change(ByVal target As Range)
Dim Cell As Range
Dim oldValue As Variant
For Each Cell In target
On Error Resume Next
oldValue = vbNullString
oldValue = dArr(Cell.Row, Cell.Column)
On Error GoTo 0
If oldValue <> Cell.Value Then
If Not Write_Change(oldValue, Cell.Value, Cell.Address) Then
MsgBox "The change was not recorded.", vbInformation
End If
End If
Next Cell
On Error Resume Next
Erase dArr
On Error GoTo 0
dArr = Me.UsedRange
End Sub
Private Sub Worksheet_SelectionChange(ByVal target As Range)
dArr = Me.UsedRange
End Sub
Public Function Write_Change(oldValue, newValue, cellAddress As String) As Boolean
Dim auditRecord As Range
On Error GoTo errHandler
Set auditRecord = Sheets("ChangeHistory").Range("A:A").Find("*", searchdirection:=xlPrevious).Offset(1, 0)
With auditRecord
.Value = cellAddress 'Address of change
.Offset(0, 1).Value = newValue 'new value
.Offset(0, 2).Value = oldValue 'previous value
.Offset(0, 3).NumberFormat = "dd mm yyyy hh:mm:ss"
.Offset(0, 3).Value = Now 'time of change
.Offset(0, 4).Value = Application.UserName 'user who made change
.Offset(0, 5).Value = Me.Range(Split(cellAddress, "$")(1) & 1).Value 'header column value
.Offset(0, 6).Value = Me.Range("D" & Split(cellAddress, "$")(2)).Value 'header row value
End With
Write_Change = True
Exit Function
errHandler:
Write_Change = False
Debug.Print "Error number: " & Err.Number
Debug.Print "Error descr: " & Err.Description
End Function
在的ThisWorkbook模块
Private Sub Workbook_Open()
dArr = Sheets("Profile").UsedRange
End Sub
说明
该解决方案的关键是公共阵列dArr
。该数组将在表格中保存一张静态值列表,并在您使用SelectionChange
事件在工作表上进行不同选择时更新。
我们使用Calculate
事件来处理公式更新单元格内容的时间。为此,我们将新值存储在表格中的数组nArr
中,然后遍历数组,并将值与dArr
中的静态值进行比较。
粘贴值或手动添加的值将使用Change
事件捕获。
为此,dArr
必须在用户打开工作簿时填写。为此,您必须将其添加到Workbook_Open
事件中,如上所示。
其他注意事项
如前所述here by Tim,有些时候,全局变量可以通过未处理的错误的方式,如果你选择使用该解决方案失去了他们的价值观,所以一定要包括良好的错误在这个项目处理。
这只写值的变化。格式化将不会使用此方法捕获。
如果配置文件页上只有一个值,则不起作用。如果需要,可以修改为像那样工作。
我在64位excel-2013上做了一些上述代码的小测试,但您可能想要进行更广泛的测试以确保所有更改都通过上述代码捕获。
不知道,但这个也许是因为由式的变化正在发生在1个多行或列的同时,如果他们是依赖于其他细胞,因此你的代码的第一或第二线退出做任何事情之前子。如果你可以在你的问题中复制和粘贴代码,而不是附加那些很棒的图片,并且你可以添加工作表的图片来显示足以确认这是否是原因的公式。 – newguy
我删除了这两行,但仍然没有工作....我不知道我在做什么错。好吧,让我粘贴。 –
当您说“外部链接到其他工作表”时,是指在同一个工作簿或不同的工作簿中? – ARich