insert comment to track changes

samst

Board Regular
Joined
Feb 12, 2003
Messages
71
I was wondering if its possible to have excel automatically insert a comment into the cell where the text or values were changed by inserting 2 things
1. Last changed on: (Date)
2. Old Value Was: (Insert the old value)

Any ideas?

Thanks
S.


I put instant coffee in a microwave and almost went back in time...
 

Excel Facts

Which came first: VisiCalc or Lotus 1-2-3?
Dan Bricklin and Bob Frankston debuted VisiCalc in 1979 as a Visible Calculator. Lotus 1-2-3 debuted in the early 1980's, from Mitch Kapor.
Public LastValue
Private Sub Worksheet_Change(ByVal Target As Range)
If Target.Count = 1 Then
With Target
On Error Resume Next
.AddComment
.Comment.Visible = False
.Comment.Text Text:="Mod on: " & Date & Chr(10) & "LastValue: " & LastValue
End With
End If
End Sub

Private Sub Worksheet_SelectionChange(ByVal Target As Range)
If Target.Count = 1 Then
LastValue = Target.Value
End If
End Sub


INSTALLATION INSTRUCTIONS:
1.click on sheet you want procedrue to work for
2.Right click on the sheet's "Name TAB"
3.In the "Tabs" drop down menu select "View Code"
4. Paste the above code into the VBE window that appears and then close
 
Upvote 0
Hi Nimrod,
I'm able to use that code also.
What would you add to the code to keep track of the last 2, 3, or n changes?
 
Upvote 0
Are you aware the excel has built in features to track changes ?
For more information goto help and type in "track changes"
 
Upvote 0
Yes, but only shows last change, shares workbook, locks macros for editing.
Your code is better. Still would like to see last couple of changes in cell.
 
Upvote 0
If you want that kind of detail how about a hidden sheet that records ALL changes in your specified sheet. Then you could filter by cell address, date, person logged in etc !

In the following procedure:
1. All changes on a specific sheet are recorded to a hidden sheet called "changes"
2. Items recorded are : Cell address, Old value, new value, date and who made change.

INSTALLTION INSTRUCTIONS:
1. Make sheet called "Changes"

2. Install following code to the specific sheet :

Public LastValue

Private Sub Worksheet_Change(ByVal Target As Range)
If Target.Count = 1 Then
With Sheets("Changes")
NxRow = .Cells(65536, 1).End(xlUp).Row + 1
.Cells(NxRow, 1).Value = Target.Address
.Cells(NxRow, 2).Value = LastValue
.Cells(NxRow, 3).Value = Target.Value
.Cells(NxRow, 4).Value = Date
.Cells(NxRow, 5).Value = Module1.GetUserName

End With
End If
End Sub

Private Sub Worksheet_SelectionChange(ByVal Target As Range)
If Target.Count = 1 Then
LastValue = Target.Value
End If
End Sub

3. Create a Module1 and install the following code at the top of the module1

Option Explicit
' This is used by GetUserName() to find the current user's
' name from the API
Declare Function Get_User_Name Lib "advapi32.dll" Alias _
"GetUserNameA" (ByVal lpBuffer As String, _
nSize As Long) As Long
Function GetUserName() As String
Dim lpBuff As String * 25

Get_User_Name lpBuff, 25
GetUserName = Left(lpBuff, InStr(lpBuff, Chr(0)) - 1)
End Function
 
Upvote 0
The code below leverages some of Nimrod's ideas, corrects a tiny glitch in his code, and keeps the data in cell comments.

The result will look like:
<blockquote>
Owner 11/2/2003 22:27:45: {=TAN(B1:B3*PI())} (-0.1249387366083->-1)
Owner 11/2/2003 22:27:52: (-1->)
Owner 11/2/2003 22:28:03: =LOG(B3:B5) (->-0.1249387366083)
Owner 11/2/2003 22:28:39: =Sheet2!A1 (-0.1249387366083->21)
Owner 11/2/2003 22:33:19: 45.3 (21->45.3)
Owner 11/2/2003 22:33:26: xyz (45.3->xyz)
Owner 11/2/2003 22:38:33: =NOW() (xyz->11/2/2003 22:38:34)
Owner 11/2/2003 22:39:00: =TODAY() (11/2/2003 22:38:34->11/2/2003)</blockquote>
Together with a timestamp, it gives the new formula, together with an indicator if it is an array formula, as well as the old value and the new value. The old value is defined as the value when the cell was selected or when the cell content was modified, whichever was later.

So, it leaves a tiny window where the old value may not be accurate. This window is the following: Suppose you select a cell. Then, use F9 to recalculate the worksheet -- and the recalculation changes the cell value. Now, you change the cell contents. In this case, the reported old value will be the value at the time the cell was selected, not after the recalculation.

In the worksheet module:
Code:
Option Explicit

Dim currUserName As String, LastValue As Variant
    Sub AddNewData(aCell As Range, LastValue)
        On Error Resume Next
        Dim aComment As Comment, CellFormula As String
        With aCell
        Set aComment = .Comment
        On Error GoTo ErrXIT
        Application.EnableEvents = False
        If aComment Is Nothing Then Set aComment = .AddComment
        CellFormula = .Formula
        If .HasArray Then CellFormula = "{" & CellFormula & "}"
        .Comment.Text .Comment.Text() _
            & currUserName & " " & Date & " " & Time() & ": " _
            & CellFormula _
            & " (" & LastValue & "->" & .Value & ")" & vbLf, 1
            End With
ErrXIT:
        Application.EnableEvents = True
        End Sub
Sub saveValues(Target As Range)
    Dim i As Long
    ReDim LastValue(1 To Target.Cells.Count)
    For i = LBound(LastValue) To UBound(LastValue)
        LastValue(i) = Target.Cells(i).Value
        Next i
    End Sub
Private Sub Worksheet_Change(ByVal Target As Range)
    Dim i As Long
    If currUserName = "" Then currUserName = GetUserName()
    If InStr(1, TypeName(LastValue), "(") > 0 Then
        For i = 1 To Target.Cells.Count
            AddNewData Target.Cells(i), LastValue(i)
            Next i
    Else
        For i = 1 To Target.Cells.Count
            AddNewData Target.Cells(i), LastValue
            'not really sure if LastValue makes sense here ;-)
            Next i
        End If
    saveValues Target
    End Sub
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
    saveValues Target
    End Sub
In a normal module:
Code:
Option Explicit
Option Private Module
Private Declare Function Get_User_Name Lib "advapi32.dll" Alias _
        "GetUserNameA" (ByVal lpBuffer As String, _
        nSize As Long) As Long
Public Function GetUserName() As String
    Dim lpBuff As String
    lpBuff = String(255, Chr(0))
    Get_User_Name lpBuff, 255
    GetUserName = Left(lpBuff, InStr(lpBuff, Chr(0)) - 1)
    End Function

If you ask for enhancements, some of which I can already think of, I won't be able to help you. Having spent way more than the budgeted time on this, I have added to an already onerous backlog. Hopefully, someone else will pitch in.

newshound12 said:
Yes, but only shows last change, shares workbook, locks macros for editing.
Your code is better. Still would like to see last couple of changes in cell.
 
Upvote 0

Forum statistics

Threads
1,215,324
Messages
6,124,249
Members
449,149
Latest member
mwdbActuary

We've detected that you are using an adblocker.

We have a great community of people providing Excel help here, but the hosting costs are enormous. You can help keep this site running by allowing ads on MrExcel.com.
Allow Ads at MrExcel

Which adblocker are you using?

Disable AdBlock

Follow these easy steps to disable AdBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the icon in the browser’s toolbar.
2)Click on the "Pause on this site" option.
Go back

Disable AdBlock Plus

Follow these easy steps to disable AdBlock Plus

1)Click on the icon in the browser’s toolbar.
2)Click on the toggle to disable it for "mrexcel.com".
Go back

Disable uBlock Origin

Follow these easy steps to disable uBlock Origin

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back

Disable uBlock

Follow these easy steps to disable uBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back
Back
Top