有可能是一個更好的方式來做到這一點,但這是來到我的腦海:
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