2016-02-19 56 views
2

我是新來這個論壇,但已經建立在近一由於我目前的角色VBA要求幾個月我的編碼經驗。今天的問題已經看到我通過許多網站(以及我的Excel VBA for Dummies書籍)進行搜索,但我還沒有完全確定它。MS Excel工作表更改事件 - 保留舊的單元格值的記錄對新價值

我試圖在Excel中的審計跟蹤文件對於我們公司風險登記。這個想法是,一旦建立了風險登記簿,任何變更都將創建一個審計線索(在單獨的選項卡上),其中顯示舊記錄和新記錄。

我已經寫了使用更改事件處理程序的代碼。我希望我的宏火每次有一個變化的時間和執行以下操作:
請對「審計(什麼用戶剛剛覆蓋)舊的單元格值的參考
2.跳轉跟蹤」標籤,貼全風險記錄的兩個副本 - 每個風險戰績佔據17列
在這17列的第一個副本的一行數據,制定出哪一列是被編輯過並更換該小區與舊單元格值(在步驟1中捕獲)
4.插入時間戳
5.有條件格式化突出顯示已更改的記錄[此功能在代碼中不需要,因爲我已在電子表格中設置它]
6.跳回到用戶剛剛製作的單元他們的編輯(在'風險註冊'選項卡上)

我已經管理步驟1,2和4-7,但我有問題獲取代碼以將「舊單元格值」輸入到「審計」中的正確位置跟蹤器「選項卡。如果我手動定義要粘貼的單元格區域,我可以在那裏找到它,但似乎無法使其變爲動態,以便它會自動識別用戶正在更改的字段,並確保在審覈中修改相同的字段落後。

真的很感激任何見解,爲什麼「PasteRange.Value =工作表(」風險登記冊「)(oldValuePaste「)」行不工作

我的代碼如下範圍。」:

Dim oldValue As Variant 
    Dim LastRow As Long 
    Private Sub Worksheet_SelectionChange(ByVal Target As Range) 
     Application.ScreenUpdating = False 
      If Not Intersect(Target, Range("b13:r13")) Is Nothing Then 
       oldValue = Target.Value 
      End If 
     Application.ScreenUpdating = True 
    End Sub 

    Private Sub Worksheet_Change(ByVal Target As Range) 
     Application.ScreenUpdating = False 

    If Not Intersect(Target, Range("b13:r14")) Is Nothing Then 
     If Target.Value <> oldValue Then 
      'MsgBox "You just changed " & Target.Address 
      Cells(65, 5).Value = oldValue  'this cell is a named range called: OldValuePaste 
      Cells(66, 5).Value = Target.row  'this cell is a named range called: OldValueRowNumber 
      Cells(67, 5).Value = Target.Column 'this cell is a named range called: OldValueColumnNumber 

      Range(Cells(Target.row, 2), Cells(Target.row, 18)).Copy 
      'Cells(70, 2).PasteSpecial xlPasteValues 

      Call Paste_on_AuditSheet 
      Sheets("Risk Register").Activate 
      Target.Select 
      Application.CutCopyMode = False 

     End If 
    End If 

Application.ScreenUpdating = True 
End Sub 

_____________________________________________________________________________________________________ 

Sub Paste_on_AuditSheet() 
Application.ScreenUpdating = False 
Dim LastRow As Long 
Dim ColNum As Long 
Dim PasteRange As Range 
ColNum = OldValueColumnNumber 

    Sheets("Audit trail").Select 
    'MsgBox "Activated " & ActiveSheet.Name 

     'Find the last used row in a Column: column B in this example 
     With ActiveSheet 
      LastRow = .Cells(.Rows.Count, "B").End(xlUp).row 
     End With 

    Set PasteRange = Cells(LastRow, ColNum) 

'The following two lines bring in the new data and paste into old record and new record sections: 
     Cells(LastRow + 1, 2).PasteSpecial xlPasteValues 
     Cells(LastRow + 1, 20).PasteSpecial xlPasteValues 

'Then this line goes back over the piece just pasted in and changes one cell in "old record" section to what it was prior to the edit: 
     'PasteRange.Value = Worksheets("Risk Register").Range("oldValuePaste") 
'Above line of code is not working, but can get it to do the right thing using this code (although it's not dynamic): 
     Range("E3").Value = Worksheets("Risk Register").Range("oldValuePaste") 

'Add a time stamp: 
    Cells(LastRow + 1, 1) = Now 

Application.ScreenUpdating = True 
End Sub 

最後一點 - 儘管我反覆使用Application.ScreenUpdating的命令,我仍然得到一些屏幕閃爍 - 任何想法,爲什麼?

在此先感謝您的幫助!

+1

很快就'ScreenUpdating'從'Paste_on_AuditSheet'次刪除'Application.ScreenUpdating = TRUE'。它重新打開了「Worksheet_Change」事件中的其餘代碼。 –

回答

1

在審查您的代碼時,我看到了一些我認爲不會按照您的設想工作的事情,並且還認識到您的代碼可以變得更簡單,只需從Worksheet_Change事件中調用即可。

所以下面的重構的代碼,讓我知道,如果你有問題:

Private Sub Worksheet_Change(ByVal Target As Range) 

If Not Intersect(Target, Range("b13:r14")) Is Nothing Then 

    'get oldValue 
    Dim sNewVal As String, sOldVal As String 
    sNewValue = Target.Value 'store current or "new" value since this is what is stored after the cell change takes place 
    With Application 
     .EnableEvents = False 'turns off event firing so the code will not go into endless loop 
     .Undo 'undo the change (to store old value in next line) 
    End With 
    sOldValue = Target.Value 'store old value 
    Target.Value = sNewValue 'reset new value 

    Dim lCol As Long 
    lCol = Target.Column 'which column of data was changed 

    'assumes columns A-Q are 17 columns 
    Me.Range(Me.Cells(Target.Row, 1), Me.Cells(Target.Row, 17)).Copy 

    With Sheets("Audit Trail") 

     Dim lRow As Long 
     lRow = .Range("B" & .Rows.Count).End(xlUp).Offset(1).Row 

     .Range("B" & lRow).PasteSpecial xlPasteValues 
     .Range("B" & lRow + 1).PasteSpecial xlPasteValues 
     .Range("A" & lRow).Value = Now 

     .Cells(lRow, lCol + 1).Value = sOldValue 'store old value in first pasted line ... add 1 since starting from column B 

    End With 

End If 

Application.EnableEvents = True 

End Sub 
+0

如果Target不是一個單元格,並且Target是多單元格但是這些單元格中只有一些*在B13:R14中,它會(如果它與> 1單元格一起工作)仍然處理整個Target'範圍,而不僅僅是B13:R14中的部分。 –

+0

感謝您指出@TimWilliams。我會讓OP告訴我他是否需要對這些問題進行調整。 –

+0

神奇的努力@ScottHoltzman - 非常感謝你的幫助。我已經採納了您的建議並用它來簡化我的代碼。重要的是,目標值字符串都是可以工作的,並且還有lCol = Target.Column維度。我已經做了一些小的修改以適應:已經設置好了,所以舊記錄和新記錄在「審計追蹤」選項卡(而不是一個在另一個之下)上並排排列,並且還使用您的提示對屏幕更新進行排序問題我有。 – Bev

相關問題