2012-08-30 12 views
1

這是一個通用的日誌系統,在這裏和我自己創建了一些人。我爲此感到自豪......我遇到了兩個問題......如果有人能夠幫助解決這個問題,那就太好了。我有一個代碼在Excel工作表中記錄使用情況,但是我得到一個錯誤和一個問題

下面是代碼:

Option Explicit 
Dim PreviousValue 

Private Sub Worksheet_Change(ByVal Target As Range) 
    Dim sLogFileName As String, nFileNum As Long, sLogMessage As String 

    sLogFileName = ThisWorkbook.path & Application.PathSeparator & "Log.txt" 

On Error Resume Next ' Turn on error handling 
    If Target.Value <> PreviousValue Then 
     ' Check if we have an error 
     If Err.Number = 13 Then 
      PreviousValue = 0 
     End If 
     ' Turn off error handling 
     On Error GoTo 0 
     sLogMessage = Now & Application.UserName & " changed cell " & Target.Address _ 
     & " from " & PreviousValue & " to " & Target.Value 

     nFileNum = FreeFile       ' next file number 
     Open sLogFileName For Append As #nFileNum ' create the file if it doesn't exist 
     Print #nFileNum, sLogMessage    ' append information 
     Close #nFileNum        ' close the file 
    End If 
End Sub 

Private Sub Worksheet_SelectionChange(ByVal Target As Range) 
    PreviousValue = Target(1).Value 
End Sub 

這裏有兩個問題。

  1. 如果選擇了多於一次的單元格並嘗試寫入,則腳本出錯。
  2. 如果有人編輯單元格並讓它空白,它會顯示的8/30/2012 1:45:01 PM Matthew Ridge changed cell $K$3 from Test to代替8/30/2012 1:45:01 PM Matthew Ridge changed cell $K$3 from Test to Blank or Empty
+2

目標可能會返回一定範圍的單元格。作爲一個例子,你可以使用'在Target.Rows中爲每一行'循環Target中的行。你也可以找到'如果Target.Row = X','如果Target.Rows.Count = Y'和'If Not Intersect'條款有用(行/列可互換)。 – user3357963

回答

3

馬特

幾件事情

  1. On Error Resume Next不妥善處理。除非和絕對必要,否則應該避免。
  2. 當您使用Worksheet_Change事件時,最好關閉事件並在最後關閉事件以避免可能的無限循環。
  3. 如果您關閉事件,那麼您必須使用適當的錯誤處理。
  4. 由於您只是在PreviousValue中存儲單個單元,所以我假設您不希望代碼在用戶選擇多個單元時運行?

我認爲這是你正在嘗試的(UNTESTED)?

Option Explicit 

Dim PreviousValue 

Private Sub Worksheet_Change(ByVal Target As Range) 
    Dim sLogFileName As String, nFileNum As Long, sLogMessage As String 
    Dim NewVal 

    On Error GoTo Whoa 

    Application.EnableEvents = False 

    sLogFileName = ThisWorkbook.Path & Application.PathSeparator & "Log.txt" 

    If Not Target.Cells.Count > 1 Then 
     If Target.Value <> PreviousValue Then 
      If Len(Trim(Target.Value)) = 0 Then _ 
      NewVal = "Blank" Else NewVal = Target.Value 

      sLogMessage = Now & Application.UserName & _ 
      " changed cell " & Target.Address & " from " & _ 
      PreviousValue & " to " & NewVal 

      nFileNum = FreeFile 
      Open sLogFileName For Append As #nFileNum 
      Print #nFileNum, sLogMessage 
      Close #nFileNum 
     End If 
    End If 
LetsContinue: 
    Application.EnableEvents = True 
    Exit Sub 
Whoa: 
    MsgBox Err.Description 
    Resume LetsContinue 
End Sub 

Private Sub Worksheet_SelectionChange(ByVal Target As Range) 
    PreviousValue = Target(1).Value 
End Sub 
+0

我在正確的上下文中使用'On Error Resume Next'沒有問題。例如,加速時間關鍵代碼非常有價值。 – user3357963

+0

'在正確的上下文中.'是在正確的上下文中;)然而,原始代碼不屬於'正確的上下文'也當Err.Number不是'13'時會發生什麼? –

+0

@SiddharthRout實際上代碼已經過測試,或者是幾個月前我開始使用它的代碼,除了我的兩個bug之外,它的工作非常完美...因此我在尋找幫助。自那時起我添加了一些功能,但沒有發佈,因爲它們被合併到模塊本身中,而不是像這樣的工作簿本身。 –

1

這對我有用。理想情況下,您可以在被跟蹤的工作表上使用命名範圍,您可以使用該範圍將跟蹤範圍限制爲僅在該範圍內發生的更改。

Const MAX_TRACKED_CELLS As Long = 50 
Dim PreviousValues As Object 

Private Sub Worksheet_Change(ByVal Target As Range) 
    Dim c As Range 
    Dim haveDict As Boolean, val, addr 

    haveDict = Not PreviousValues Is Nothing 

    If Target.Cells.Count <= MAX_TRACKED_CELLS Then 
     For Each c In Target.Cells 
      addr = c.Address() 
      If haveDict Then 
       If PreviousValues.exists(addr) Then 
        val = PreviousValues(addr) 
       End If 
      Else 
       val = "{unknown}" 
      End If 

      If c.Value <> val Then 
       Debug.Print "Changed:", addr, IIf(val = "", "Empty", val), _ 
          " to ", IIf(c.Value = "", "Empty", c.Value) 
      End If 

     Next c 
    End If 


End Sub 

Private Sub Worksheet_SelectionChange(ByVal Target As Range) 
    Dim c As Range 

    If PreviousValues Is Nothing Then 
     Set PreviousValues = CreateObject("scripting.dictionary") 
    Else 
     PreviousValues.RemoveAll 
    End If 

    If Target.Cells.Count <= MAX_TRACKED_CELLS Then 
     For Each c In Target.Cells 
      PreviousValues.Add c.Address(), c.Value 
     Next c 
    End If 

End Sub 
+0

我已決定與你和Siddharth Rout合併在一起......非常感謝你的幫助:) –

+0

我正在嘗試你的腳本,只有一個問題,Max_tracked_cells是什麼?沒有任何記錄...... –

+0

這是一個避免嘗試跟蹤太多單元格的常量,它在我的發佈代碼的頂部被聲明,所以我不確定你的意思是「沒有它的記錄」 ?如果(例如)用戶在Excel2007 +中插入列,則不希望開始將1M +單元格的內容記錄到字典中。同上行/列刪除。正如我在帖子中提到的那樣,最好在被跟蹤的工作表上設置一個命名範圍,這樣就可以使用它來限制觸發日誌記錄的工作表上的區域(通過將'Target'與該範圍相交以限制什麼你試圖記錄)。 –

相關問題