Create log history for a cell value change in a column












0















I create a log history worksheet and save the change detail of other worksheets.



Dim oldValue As Variant

Private Sub Workbook_SheetChange(ByVal Sh As Object, ByVal Target As Range)
Dim sSheetName As String
sSheetName = "Data"
If ActiveSheet.Name <> "LogDetails" Then
Application.EnableEvents = False
Sheets("LogDetails").Range("A" & Rows.Count).End(xlUp).Offset(1, 0).Value = ActiveSheet.Name & "-" & Target.Address(0, 0)
Sheets("LogDetails").Range("A" & Rows.Count).End(xlUp).Offset(0, 1).Value = oldValue
Sheets("LogDetails").Range("A" & Rows.Count).End(xlUp).Offset(0, 2).Value = Target.Formula
Sheets("LogDetails").Range("A" & Rows.Count).End(xlUp).Offset(0, 3).Value = Environ("username")
Sheets("LogDetails").Range("A" & Rows.Count).End(xlUp).Offset(0, 4).Value = Now

Sheets("LogDetails").Columns("A:D").AutoFit
Application.EnableEvents = True
End If
End Sub

Private Sub Workbook_SheetSelectionChange(ByVal Sh As Object, ByVal Target As Range)
oldValue = Target.Formula
End Sub


That works for a single cell, e.g.:



If A1 stores "ABC" and changes to "123", Log Detail will save the Cell address, old value, new value, username and date/time.



The big problem is when I select a whole column, such as all of column(B). It will get the error




"type not match".




I know the problem is



oldValue = Target.Value


How can I save the change of a column?










share|improve this question

























  • What do you want to happen? I don't really understand "that it also can save the change of column". Do you want to log a selection change? A modification of multiple cells is not easily done by the user, except maybe for Copy+Pasting. The issue with oldValue = Target.Value is that when multiple cells are selected, Target.Value will return an array, which you can't store in a simple string variable. Thus the type mismatch. So you need to decide what exactly you want to happen in case of a multi-cell selection? Maybe force the selection to only the first cell?

    – Inarion
    Nov 21 '18 at 10:31













  • Also think of the implications of logging multiple changes at the same time: Should a change in all cells of a column (so 1048576 changes) all be logged on their own? Your log sheet will be instantly filled up. Or do you want to somehow compress these changes into fewer lines? (How so?)

    – Inarion
    Nov 21 '18 at 10:33











  • sorry for late response, the thing i want to do is, for example, if i change in range("A1") formula: =C1+D1 and then selection a range such as A1-A20 and then Ctrl+D to replace the formula to whole selection. In my mind the record should show 2 record. first one is i replace the formula in range A1 second is i replace the formula in range A2-A20 but i dun know how to display it....

    – Nicawong9147
    Nov 22 '18 at 1:25











  • the first i do this vba is i want the change in all cells of a column would be logged on their own, i know that's will be fill up instantly. but my workbook file sometimes got more 2000 record. that would be a great and long process time to do it, so if possbile, 2 record will be show in it.

    – Nicawong9147
    Nov 22 '18 at 1:35













  • there is another problem is, when i change the formula of a cell and logged it. the logdetail only show the change of value, not change of formula.(i hope it show =A1+B1 in target . value, something like that). can it be change the display format?

    – Nicawong9147
    Nov 22 '18 at 1:38


















0















I create a log history worksheet and save the change detail of other worksheets.



Dim oldValue As Variant

Private Sub Workbook_SheetChange(ByVal Sh As Object, ByVal Target As Range)
Dim sSheetName As String
sSheetName = "Data"
If ActiveSheet.Name <> "LogDetails" Then
Application.EnableEvents = False
Sheets("LogDetails").Range("A" & Rows.Count).End(xlUp).Offset(1, 0).Value = ActiveSheet.Name & "-" & Target.Address(0, 0)
Sheets("LogDetails").Range("A" & Rows.Count).End(xlUp).Offset(0, 1).Value = oldValue
Sheets("LogDetails").Range("A" & Rows.Count).End(xlUp).Offset(0, 2).Value = Target.Formula
Sheets("LogDetails").Range("A" & Rows.Count).End(xlUp).Offset(0, 3).Value = Environ("username")
Sheets("LogDetails").Range("A" & Rows.Count).End(xlUp).Offset(0, 4).Value = Now

Sheets("LogDetails").Columns("A:D").AutoFit
Application.EnableEvents = True
End If
End Sub

Private Sub Workbook_SheetSelectionChange(ByVal Sh As Object, ByVal Target As Range)
oldValue = Target.Formula
End Sub


That works for a single cell, e.g.:



If A1 stores "ABC" and changes to "123", Log Detail will save the Cell address, old value, new value, username and date/time.



The big problem is when I select a whole column, such as all of column(B). It will get the error




"type not match".




I know the problem is



oldValue = Target.Value


How can I save the change of a column?










share|improve this question

























  • What do you want to happen? I don't really understand "that it also can save the change of column". Do you want to log a selection change? A modification of multiple cells is not easily done by the user, except maybe for Copy+Pasting. The issue with oldValue = Target.Value is that when multiple cells are selected, Target.Value will return an array, which you can't store in a simple string variable. Thus the type mismatch. So you need to decide what exactly you want to happen in case of a multi-cell selection? Maybe force the selection to only the first cell?

    – Inarion
    Nov 21 '18 at 10:31













  • Also think of the implications of logging multiple changes at the same time: Should a change in all cells of a column (so 1048576 changes) all be logged on their own? Your log sheet will be instantly filled up. Or do you want to somehow compress these changes into fewer lines? (How so?)

    – Inarion
    Nov 21 '18 at 10:33











  • sorry for late response, the thing i want to do is, for example, if i change in range("A1") formula: =C1+D1 and then selection a range such as A1-A20 and then Ctrl+D to replace the formula to whole selection. In my mind the record should show 2 record. first one is i replace the formula in range A1 second is i replace the formula in range A2-A20 but i dun know how to display it....

    – Nicawong9147
    Nov 22 '18 at 1:25











  • the first i do this vba is i want the change in all cells of a column would be logged on their own, i know that's will be fill up instantly. but my workbook file sometimes got more 2000 record. that would be a great and long process time to do it, so if possbile, 2 record will be show in it.

    – Nicawong9147
    Nov 22 '18 at 1:35













  • there is another problem is, when i change the formula of a cell and logged it. the logdetail only show the change of value, not change of formula.(i hope it show =A1+B1 in target . value, something like that). can it be change the display format?

    – Nicawong9147
    Nov 22 '18 at 1:38
















0












0








0








I create a log history worksheet and save the change detail of other worksheets.



Dim oldValue As Variant

Private Sub Workbook_SheetChange(ByVal Sh As Object, ByVal Target As Range)
Dim sSheetName As String
sSheetName = "Data"
If ActiveSheet.Name <> "LogDetails" Then
Application.EnableEvents = False
Sheets("LogDetails").Range("A" & Rows.Count).End(xlUp).Offset(1, 0).Value = ActiveSheet.Name & "-" & Target.Address(0, 0)
Sheets("LogDetails").Range("A" & Rows.Count).End(xlUp).Offset(0, 1).Value = oldValue
Sheets("LogDetails").Range("A" & Rows.Count).End(xlUp).Offset(0, 2).Value = Target.Formula
Sheets("LogDetails").Range("A" & Rows.Count).End(xlUp).Offset(0, 3).Value = Environ("username")
Sheets("LogDetails").Range("A" & Rows.Count).End(xlUp).Offset(0, 4).Value = Now

Sheets("LogDetails").Columns("A:D").AutoFit
Application.EnableEvents = True
End If
End Sub

Private Sub Workbook_SheetSelectionChange(ByVal Sh As Object, ByVal Target As Range)
oldValue = Target.Formula
End Sub


That works for a single cell, e.g.:



If A1 stores "ABC" and changes to "123", Log Detail will save the Cell address, old value, new value, username and date/time.



The big problem is when I select a whole column, such as all of column(B). It will get the error




"type not match".




I know the problem is



oldValue = Target.Value


How can I save the change of a column?










share|improve this question
















I create a log history worksheet and save the change detail of other worksheets.



Dim oldValue As Variant

Private Sub Workbook_SheetChange(ByVal Sh As Object, ByVal Target As Range)
Dim sSheetName As String
sSheetName = "Data"
If ActiveSheet.Name <> "LogDetails" Then
Application.EnableEvents = False
Sheets("LogDetails").Range("A" & Rows.Count).End(xlUp).Offset(1, 0).Value = ActiveSheet.Name & "-" & Target.Address(0, 0)
Sheets("LogDetails").Range("A" & Rows.Count).End(xlUp).Offset(0, 1).Value = oldValue
Sheets("LogDetails").Range("A" & Rows.Count).End(xlUp).Offset(0, 2).Value = Target.Formula
Sheets("LogDetails").Range("A" & Rows.Count).End(xlUp).Offset(0, 3).Value = Environ("username")
Sheets("LogDetails").Range("A" & Rows.Count).End(xlUp).Offset(0, 4).Value = Now

Sheets("LogDetails").Columns("A:D").AutoFit
Application.EnableEvents = True
End If
End Sub

Private Sub Workbook_SheetSelectionChange(ByVal Sh As Object, ByVal Target As Range)
oldValue = Target.Formula
End Sub


That works for a single cell, e.g.:



If A1 stores "ABC" and changes to "123", Log Detail will save the Cell address, old value, new value, username and date/time.



The big problem is when I select a whole column, such as all of column(B). It will get the error




"type not match".




I know the problem is



oldValue = Target.Value


How can I save the change of a column?







excel vba






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Jan 9 at 14:19









Cindy Meister

15.8k102437




15.8k102437










asked Nov 21 '18 at 9:42









Nicawong9147Nicawong9147

105




105













  • What do you want to happen? I don't really understand "that it also can save the change of column". Do you want to log a selection change? A modification of multiple cells is not easily done by the user, except maybe for Copy+Pasting. The issue with oldValue = Target.Value is that when multiple cells are selected, Target.Value will return an array, which you can't store in a simple string variable. Thus the type mismatch. So you need to decide what exactly you want to happen in case of a multi-cell selection? Maybe force the selection to only the first cell?

    – Inarion
    Nov 21 '18 at 10:31













  • Also think of the implications of logging multiple changes at the same time: Should a change in all cells of a column (so 1048576 changes) all be logged on their own? Your log sheet will be instantly filled up. Or do you want to somehow compress these changes into fewer lines? (How so?)

    – Inarion
    Nov 21 '18 at 10:33











  • sorry for late response, the thing i want to do is, for example, if i change in range("A1") formula: =C1+D1 and then selection a range such as A1-A20 and then Ctrl+D to replace the formula to whole selection. In my mind the record should show 2 record. first one is i replace the formula in range A1 second is i replace the formula in range A2-A20 but i dun know how to display it....

    – Nicawong9147
    Nov 22 '18 at 1:25











  • the first i do this vba is i want the change in all cells of a column would be logged on their own, i know that's will be fill up instantly. but my workbook file sometimes got more 2000 record. that would be a great and long process time to do it, so if possbile, 2 record will be show in it.

    – Nicawong9147
    Nov 22 '18 at 1:35













  • there is another problem is, when i change the formula of a cell and logged it. the logdetail only show the change of value, not change of formula.(i hope it show =A1+B1 in target . value, something like that). can it be change the display format?

    – Nicawong9147
    Nov 22 '18 at 1:38





















  • What do you want to happen? I don't really understand "that it also can save the change of column". Do you want to log a selection change? A modification of multiple cells is not easily done by the user, except maybe for Copy+Pasting. The issue with oldValue = Target.Value is that when multiple cells are selected, Target.Value will return an array, which you can't store in a simple string variable. Thus the type mismatch. So you need to decide what exactly you want to happen in case of a multi-cell selection? Maybe force the selection to only the first cell?

    – Inarion
    Nov 21 '18 at 10:31













  • Also think of the implications of logging multiple changes at the same time: Should a change in all cells of a column (so 1048576 changes) all be logged on their own? Your log sheet will be instantly filled up. Or do you want to somehow compress these changes into fewer lines? (How so?)

    – Inarion
    Nov 21 '18 at 10:33











  • sorry for late response, the thing i want to do is, for example, if i change in range("A1") formula: =C1+D1 and then selection a range such as A1-A20 and then Ctrl+D to replace the formula to whole selection. In my mind the record should show 2 record. first one is i replace the formula in range A1 second is i replace the formula in range A2-A20 but i dun know how to display it....

    – Nicawong9147
    Nov 22 '18 at 1:25











  • the first i do this vba is i want the change in all cells of a column would be logged on their own, i know that's will be fill up instantly. but my workbook file sometimes got more 2000 record. that would be a great and long process time to do it, so if possbile, 2 record will be show in it.

    – Nicawong9147
    Nov 22 '18 at 1:35













  • there is another problem is, when i change the formula of a cell and logged it. the logdetail only show the change of value, not change of formula.(i hope it show =A1+B1 in target . value, something like that). can it be change the display format?

    – Nicawong9147
    Nov 22 '18 at 1:38



















What do you want to happen? I don't really understand "that it also can save the change of column". Do you want to log a selection change? A modification of multiple cells is not easily done by the user, except maybe for Copy+Pasting. The issue with oldValue = Target.Value is that when multiple cells are selected, Target.Value will return an array, which you can't store in a simple string variable. Thus the type mismatch. So you need to decide what exactly you want to happen in case of a multi-cell selection? Maybe force the selection to only the first cell?

– Inarion
Nov 21 '18 at 10:31







What do you want to happen? I don't really understand "that it also can save the change of column". Do you want to log a selection change? A modification of multiple cells is not easily done by the user, except maybe for Copy+Pasting. The issue with oldValue = Target.Value is that when multiple cells are selected, Target.Value will return an array, which you can't store in a simple string variable. Thus the type mismatch. So you need to decide what exactly you want to happen in case of a multi-cell selection? Maybe force the selection to only the first cell?

– Inarion
Nov 21 '18 at 10:31















Also think of the implications of logging multiple changes at the same time: Should a change in all cells of a column (so 1048576 changes) all be logged on their own? Your log sheet will be instantly filled up. Or do you want to somehow compress these changes into fewer lines? (How so?)

– Inarion
Nov 21 '18 at 10:33





Also think of the implications of logging multiple changes at the same time: Should a change in all cells of a column (so 1048576 changes) all be logged on their own? Your log sheet will be instantly filled up. Or do you want to somehow compress these changes into fewer lines? (How so?)

– Inarion
Nov 21 '18 at 10:33













sorry for late response, the thing i want to do is, for example, if i change in range("A1") formula: =C1+D1 and then selection a range such as A1-A20 and then Ctrl+D to replace the formula to whole selection. In my mind the record should show 2 record. first one is i replace the formula in range A1 second is i replace the formula in range A2-A20 but i dun know how to display it....

– Nicawong9147
Nov 22 '18 at 1:25





sorry for late response, the thing i want to do is, for example, if i change in range("A1") formula: =C1+D1 and then selection a range such as A1-A20 and then Ctrl+D to replace the formula to whole selection. In my mind the record should show 2 record. first one is i replace the formula in range A1 second is i replace the formula in range A2-A20 but i dun know how to display it....

– Nicawong9147
Nov 22 '18 at 1:25













the first i do this vba is i want the change in all cells of a column would be logged on their own, i know that's will be fill up instantly. but my workbook file sometimes got more 2000 record. that would be a great and long process time to do it, so if possbile, 2 record will be show in it.

– Nicawong9147
Nov 22 '18 at 1:35







the first i do this vba is i want the change in all cells of a column would be logged on their own, i know that's will be fill up instantly. but my workbook file sometimes got more 2000 record. that would be a great and long process time to do it, so if possbile, 2 record will be show in it.

– Nicawong9147
Nov 22 '18 at 1:35















there is another problem is, when i change the formula of a cell and logged it. the logdetail only show the change of value, not change of formula.(i hope it show =A1+B1 in target . value, something like that). can it be change the display format?

– Nicawong9147
Nov 22 '18 at 1:38







there is another problem is, when i change the formula of a cell and logged it. the logdetail only show the change of value, not change of formula.(i hope it show =A1+B1 in target . value, something like that). can it be change the display format?

– Nicawong9147
Nov 22 '18 at 1:38














1 Answer
1






active

oldest

votes


















0














I'm not entirely sure if that solves your problem, but try the following modification to your Workbook_SheetSelectionChange procedure:



Private Sub Workbook_SheetSelectionChange(ByVal Sh As Object, ByVal Target As Range)
If Target.Count > 1 Then
Target(1).Select
Exit Sub
End If
oldValue = Target.Value
oldAddress = Target.Address
End Sub


Every time the user selects more than one cell the event procedure will change that selection (which raises another change event, with a single-cell target this time) and exit without doing anything else. The criterion for when this selection change should happen can of course be refined to allow for a more specific behavior.



This should make it much harder for the average user to intentionally or accidentally modify more than one cell at a time.





To address questions from your comments:




the undo function of excel cannot be used




This is true. Excel doesn't know how to reverse the actions your code has taken. You need to build this functionality yourself. See this question + accepted answer.




the formula change show in log sheet cannot not show properly, it will show 0 or #Value!




Yes, that's by design. With the line



Sheets("LogDetails").Range("A" & Rows.Count).End(xlUp).Offset(0, 2).Value = Target.Formula


you tell Excel to set that cell's value to a formula. Which Excel then automatically tries to evaluate. (Leading to the errors you're experiencing)

Try the following:



' Prepend the formula with an apostrophe
Sheets("LogDetails").Range("A" & Rows.Count).End(xlUp).Offset(0, 2).Value = "'" & Target.Formula


This will force Excel to treat the cell value as text and thus it will simply show the formula without evaluating it.




copy and paste a range only show the first cell changes, is it cannot be fix?




This is due to oldValues being an array while you only ever access its first value. See my implementation:



Option Explicit

Dim oldValues As Variant

Private Sub Workbook_SheetChange(ByVal Sh As Object, ByVal Target As Range)

Const LogSheet As String = "LogDetails"

If Sh.Name = LogSheet Then Exit Sub

Application.EnableEvents = False

With Worksheets(LogSheet)

Dim idxRows As Long
For idxRows = 1 To Target.Rows.Count

Dim idxCols As Long
For idxCols = 1 To Target.Columns.Count

Dim ChangedCell As Range
Set ChangedCell = Target.Rows(idxRows).Columns(idxCols)

Dim LogRow As Long
LogRow = .Range("A" & Rows.Count).End(xlUp).Row + 1
Dim LogRange As Range
Set LogRange = .Range(.Cells(LogRow, 1), .Cells(LogRow, 5))

LogRange(1).Value = Sh.Name & "!" & ChangedCell.Address(False, False)
LogRange(2).Value = "'" & oldValues(idxRows, idxCols) ' error here when pasting a range of different size than has been selected before pasting
LogRange(3).Value = ChangedCell.Formula
LogRange(4).Value = Environ("username")
LogRange(5).Value = Now

Next idxCols

Next idxRows

.Columns("A:E").AutoFit

End With

Application.EnableEvents = True

End Sub

Private Sub Workbook_SheetSelectionChange(ByVal Sh As Object, ByVal Target As Range)
oldValues = Target.Formula
End Sub


This has the weakness that when a user copies multiple cells and then selects a single cell and pastes, it will error out, due to mismatching indices. (It works when you copy, e.g. 3 cells in a row, then select 3 other cells in a row and paste.) Not sure how to avoid that. We'd need to capture the size of the pasted range to update oldValues accordingly. As Excel doesn't expose a Workbook_SheetBeforePaste event, that seems rather tricky.






share|improve this answer


























  • Sorry for late response @Inarion, I have assignment these 2 days, really sorry for late. i have tested your code, but when i input something in a black cell, it shows me the error. "type mismatch", what's wrong with it?

    – Nicawong9147
    Nov 26 '18 at 3:51













  • @Nicawong9147 I'm not sure what a cell's color has to do with any of this? Can you make sure there's no other property of that cell that could be the culprit?

    – Inarion
    Nov 27 '18 at 16:39











  • Sorry, Wrong typing, should be blank cell, not black cell.i put your code in the Thisworkbook and build the LogDetails sheet. No matter what i am input in Sheet1, Sheet2 or Sheet3, just show me the type mismatch.

    – Nicawong9147
    Nov 29 '18 at 1:19











  • The error code show in this code: LogRange(2).Value = "'" & oldValues(idxRows, idxCols)

    – Nicawong9147
    Nov 29 '18 at 1:22











Your Answer






StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");

StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});

function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});


}
});














draft saved

draft discarded


















StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53409158%2fcreate-log-history-for-a-cell-value-change-in-a-column%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown

























1 Answer
1






active

oldest

votes








1 Answer
1






active

oldest

votes









active

oldest

votes






active

oldest

votes









0














I'm not entirely sure if that solves your problem, but try the following modification to your Workbook_SheetSelectionChange procedure:



Private Sub Workbook_SheetSelectionChange(ByVal Sh As Object, ByVal Target As Range)
If Target.Count > 1 Then
Target(1).Select
Exit Sub
End If
oldValue = Target.Value
oldAddress = Target.Address
End Sub


Every time the user selects more than one cell the event procedure will change that selection (which raises another change event, with a single-cell target this time) and exit without doing anything else. The criterion for when this selection change should happen can of course be refined to allow for a more specific behavior.



This should make it much harder for the average user to intentionally or accidentally modify more than one cell at a time.





To address questions from your comments:




the undo function of excel cannot be used




This is true. Excel doesn't know how to reverse the actions your code has taken. You need to build this functionality yourself. See this question + accepted answer.




the formula change show in log sheet cannot not show properly, it will show 0 or #Value!




Yes, that's by design. With the line



Sheets("LogDetails").Range("A" & Rows.Count).End(xlUp).Offset(0, 2).Value = Target.Formula


you tell Excel to set that cell's value to a formula. Which Excel then automatically tries to evaluate. (Leading to the errors you're experiencing)

Try the following:



' Prepend the formula with an apostrophe
Sheets("LogDetails").Range("A" & Rows.Count).End(xlUp).Offset(0, 2).Value = "'" & Target.Formula


This will force Excel to treat the cell value as text and thus it will simply show the formula without evaluating it.




copy and paste a range only show the first cell changes, is it cannot be fix?




This is due to oldValues being an array while you only ever access its first value. See my implementation:



Option Explicit

Dim oldValues As Variant

Private Sub Workbook_SheetChange(ByVal Sh As Object, ByVal Target As Range)

Const LogSheet As String = "LogDetails"

If Sh.Name = LogSheet Then Exit Sub

Application.EnableEvents = False

With Worksheets(LogSheet)

Dim idxRows As Long
For idxRows = 1 To Target.Rows.Count

Dim idxCols As Long
For idxCols = 1 To Target.Columns.Count

Dim ChangedCell As Range
Set ChangedCell = Target.Rows(idxRows).Columns(idxCols)

Dim LogRow As Long
LogRow = .Range("A" & Rows.Count).End(xlUp).Row + 1
Dim LogRange As Range
Set LogRange = .Range(.Cells(LogRow, 1), .Cells(LogRow, 5))

LogRange(1).Value = Sh.Name & "!" & ChangedCell.Address(False, False)
LogRange(2).Value = "'" & oldValues(idxRows, idxCols) ' error here when pasting a range of different size than has been selected before pasting
LogRange(3).Value = ChangedCell.Formula
LogRange(4).Value = Environ("username")
LogRange(5).Value = Now

Next idxCols

Next idxRows

.Columns("A:E").AutoFit

End With

Application.EnableEvents = True

End Sub

Private Sub Workbook_SheetSelectionChange(ByVal Sh As Object, ByVal Target As Range)
oldValues = Target.Formula
End Sub


This has the weakness that when a user copies multiple cells and then selects a single cell and pastes, it will error out, due to mismatching indices. (It works when you copy, e.g. 3 cells in a row, then select 3 other cells in a row and paste.) Not sure how to avoid that. We'd need to capture the size of the pasted range to update oldValues accordingly. As Excel doesn't expose a Workbook_SheetBeforePaste event, that seems rather tricky.






share|improve this answer


























  • Sorry for late response @Inarion, I have assignment these 2 days, really sorry for late. i have tested your code, but when i input something in a black cell, it shows me the error. "type mismatch", what's wrong with it?

    – Nicawong9147
    Nov 26 '18 at 3:51













  • @Nicawong9147 I'm not sure what a cell's color has to do with any of this? Can you make sure there's no other property of that cell that could be the culprit?

    – Inarion
    Nov 27 '18 at 16:39











  • Sorry, Wrong typing, should be blank cell, not black cell.i put your code in the Thisworkbook and build the LogDetails sheet. No matter what i am input in Sheet1, Sheet2 or Sheet3, just show me the type mismatch.

    – Nicawong9147
    Nov 29 '18 at 1:19











  • The error code show in this code: LogRange(2).Value = "'" & oldValues(idxRows, idxCols)

    – Nicawong9147
    Nov 29 '18 at 1:22
















0














I'm not entirely sure if that solves your problem, but try the following modification to your Workbook_SheetSelectionChange procedure:



Private Sub Workbook_SheetSelectionChange(ByVal Sh As Object, ByVal Target As Range)
If Target.Count > 1 Then
Target(1).Select
Exit Sub
End If
oldValue = Target.Value
oldAddress = Target.Address
End Sub


Every time the user selects more than one cell the event procedure will change that selection (which raises another change event, with a single-cell target this time) and exit without doing anything else. The criterion for when this selection change should happen can of course be refined to allow for a more specific behavior.



This should make it much harder for the average user to intentionally or accidentally modify more than one cell at a time.





To address questions from your comments:




the undo function of excel cannot be used




This is true. Excel doesn't know how to reverse the actions your code has taken. You need to build this functionality yourself. See this question + accepted answer.




the formula change show in log sheet cannot not show properly, it will show 0 or #Value!




Yes, that's by design. With the line



Sheets("LogDetails").Range("A" & Rows.Count).End(xlUp).Offset(0, 2).Value = Target.Formula


you tell Excel to set that cell's value to a formula. Which Excel then automatically tries to evaluate. (Leading to the errors you're experiencing)

Try the following:



' Prepend the formula with an apostrophe
Sheets("LogDetails").Range("A" & Rows.Count).End(xlUp).Offset(0, 2).Value = "'" & Target.Formula


This will force Excel to treat the cell value as text and thus it will simply show the formula without evaluating it.




copy and paste a range only show the first cell changes, is it cannot be fix?




This is due to oldValues being an array while you only ever access its first value. See my implementation:



Option Explicit

Dim oldValues As Variant

Private Sub Workbook_SheetChange(ByVal Sh As Object, ByVal Target As Range)

Const LogSheet As String = "LogDetails"

If Sh.Name = LogSheet Then Exit Sub

Application.EnableEvents = False

With Worksheets(LogSheet)

Dim idxRows As Long
For idxRows = 1 To Target.Rows.Count

Dim idxCols As Long
For idxCols = 1 To Target.Columns.Count

Dim ChangedCell As Range
Set ChangedCell = Target.Rows(idxRows).Columns(idxCols)

Dim LogRow As Long
LogRow = .Range("A" & Rows.Count).End(xlUp).Row + 1
Dim LogRange As Range
Set LogRange = .Range(.Cells(LogRow, 1), .Cells(LogRow, 5))

LogRange(1).Value = Sh.Name & "!" & ChangedCell.Address(False, False)
LogRange(2).Value = "'" & oldValues(idxRows, idxCols) ' error here when pasting a range of different size than has been selected before pasting
LogRange(3).Value = ChangedCell.Formula
LogRange(4).Value = Environ("username")
LogRange(5).Value = Now

Next idxCols

Next idxRows

.Columns("A:E").AutoFit

End With

Application.EnableEvents = True

End Sub

Private Sub Workbook_SheetSelectionChange(ByVal Sh As Object, ByVal Target As Range)
oldValues = Target.Formula
End Sub


This has the weakness that when a user copies multiple cells and then selects a single cell and pastes, it will error out, due to mismatching indices. (It works when you copy, e.g. 3 cells in a row, then select 3 other cells in a row and paste.) Not sure how to avoid that. We'd need to capture the size of the pasted range to update oldValues accordingly. As Excel doesn't expose a Workbook_SheetBeforePaste event, that seems rather tricky.






share|improve this answer


























  • Sorry for late response @Inarion, I have assignment these 2 days, really sorry for late. i have tested your code, but when i input something in a black cell, it shows me the error. "type mismatch", what's wrong with it?

    – Nicawong9147
    Nov 26 '18 at 3:51













  • @Nicawong9147 I'm not sure what a cell's color has to do with any of this? Can you make sure there's no other property of that cell that could be the culprit?

    – Inarion
    Nov 27 '18 at 16:39











  • Sorry, Wrong typing, should be blank cell, not black cell.i put your code in the Thisworkbook and build the LogDetails sheet. No matter what i am input in Sheet1, Sheet2 or Sheet3, just show me the type mismatch.

    – Nicawong9147
    Nov 29 '18 at 1:19











  • The error code show in this code: LogRange(2).Value = "'" & oldValues(idxRows, idxCols)

    – Nicawong9147
    Nov 29 '18 at 1:22














0












0








0







I'm not entirely sure if that solves your problem, but try the following modification to your Workbook_SheetSelectionChange procedure:



Private Sub Workbook_SheetSelectionChange(ByVal Sh As Object, ByVal Target As Range)
If Target.Count > 1 Then
Target(1).Select
Exit Sub
End If
oldValue = Target.Value
oldAddress = Target.Address
End Sub


Every time the user selects more than one cell the event procedure will change that selection (which raises another change event, with a single-cell target this time) and exit without doing anything else. The criterion for when this selection change should happen can of course be refined to allow for a more specific behavior.



This should make it much harder for the average user to intentionally or accidentally modify more than one cell at a time.





To address questions from your comments:




the undo function of excel cannot be used




This is true. Excel doesn't know how to reverse the actions your code has taken. You need to build this functionality yourself. See this question + accepted answer.




the formula change show in log sheet cannot not show properly, it will show 0 or #Value!




Yes, that's by design. With the line



Sheets("LogDetails").Range("A" & Rows.Count).End(xlUp).Offset(0, 2).Value = Target.Formula


you tell Excel to set that cell's value to a formula. Which Excel then automatically tries to evaluate. (Leading to the errors you're experiencing)

Try the following:



' Prepend the formula with an apostrophe
Sheets("LogDetails").Range("A" & Rows.Count).End(xlUp).Offset(0, 2).Value = "'" & Target.Formula


This will force Excel to treat the cell value as text and thus it will simply show the formula without evaluating it.




copy and paste a range only show the first cell changes, is it cannot be fix?




This is due to oldValues being an array while you only ever access its first value. See my implementation:



Option Explicit

Dim oldValues As Variant

Private Sub Workbook_SheetChange(ByVal Sh As Object, ByVal Target As Range)

Const LogSheet As String = "LogDetails"

If Sh.Name = LogSheet Then Exit Sub

Application.EnableEvents = False

With Worksheets(LogSheet)

Dim idxRows As Long
For idxRows = 1 To Target.Rows.Count

Dim idxCols As Long
For idxCols = 1 To Target.Columns.Count

Dim ChangedCell As Range
Set ChangedCell = Target.Rows(idxRows).Columns(idxCols)

Dim LogRow As Long
LogRow = .Range("A" & Rows.Count).End(xlUp).Row + 1
Dim LogRange As Range
Set LogRange = .Range(.Cells(LogRow, 1), .Cells(LogRow, 5))

LogRange(1).Value = Sh.Name & "!" & ChangedCell.Address(False, False)
LogRange(2).Value = "'" & oldValues(idxRows, idxCols) ' error here when pasting a range of different size than has been selected before pasting
LogRange(3).Value = ChangedCell.Formula
LogRange(4).Value = Environ("username")
LogRange(5).Value = Now

Next idxCols

Next idxRows

.Columns("A:E").AutoFit

End With

Application.EnableEvents = True

End Sub

Private Sub Workbook_SheetSelectionChange(ByVal Sh As Object, ByVal Target As Range)
oldValues = Target.Formula
End Sub


This has the weakness that when a user copies multiple cells and then selects a single cell and pastes, it will error out, due to mismatching indices. (It works when you copy, e.g. 3 cells in a row, then select 3 other cells in a row and paste.) Not sure how to avoid that. We'd need to capture the size of the pasted range to update oldValues accordingly. As Excel doesn't expose a Workbook_SheetBeforePaste event, that seems rather tricky.






share|improve this answer















I'm not entirely sure if that solves your problem, but try the following modification to your Workbook_SheetSelectionChange procedure:



Private Sub Workbook_SheetSelectionChange(ByVal Sh As Object, ByVal Target As Range)
If Target.Count > 1 Then
Target(1).Select
Exit Sub
End If
oldValue = Target.Value
oldAddress = Target.Address
End Sub


Every time the user selects more than one cell the event procedure will change that selection (which raises another change event, with a single-cell target this time) and exit without doing anything else. The criterion for when this selection change should happen can of course be refined to allow for a more specific behavior.



This should make it much harder for the average user to intentionally or accidentally modify more than one cell at a time.





To address questions from your comments:




the undo function of excel cannot be used




This is true. Excel doesn't know how to reverse the actions your code has taken. You need to build this functionality yourself. See this question + accepted answer.




the formula change show in log sheet cannot not show properly, it will show 0 or #Value!




Yes, that's by design. With the line



Sheets("LogDetails").Range("A" & Rows.Count).End(xlUp).Offset(0, 2).Value = Target.Formula


you tell Excel to set that cell's value to a formula. Which Excel then automatically tries to evaluate. (Leading to the errors you're experiencing)

Try the following:



' Prepend the formula with an apostrophe
Sheets("LogDetails").Range("A" & Rows.Count).End(xlUp).Offset(0, 2).Value = "'" & Target.Formula


This will force Excel to treat the cell value as text and thus it will simply show the formula without evaluating it.




copy and paste a range only show the first cell changes, is it cannot be fix?




This is due to oldValues being an array while you only ever access its first value. See my implementation:



Option Explicit

Dim oldValues As Variant

Private Sub Workbook_SheetChange(ByVal Sh As Object, ByVal Target As Range)

Const LogSheet As String = "LogDetails"

If Sh.Name = LogSheet Then Exit Sub

Application.EnableEvents = False

With Worksheets(LogSheet)

Dim idxRows As Long
For idxRows = 1 To Target.Rows.Count

Dim idxCols As Long
For idxCols = 1 To Target.Columns.Count

Dim ChangedCell As Range
Set ChangedCell = Target.Rows(idxRows).Columns(idxCols)

Dim LogRow As Long
LogRow = .Range("A" & Rows.Count).End(xlUp).Row + 1
Dim LogRange As Range
Set LogRange = .Range(.Cells(LogRow, 1), .Cells(LogRow, 5))

LogRange(1).Value = Sh.Name & "!" & ChangedCell.Address(False, False)
LogRange(2).Value = "'" & oldValues(idxRows, idxCols) ' error here when pasting a range of different size than has been selected before pasting
LogRange(3).Value = ChangedCell.Formula
LogRange(4).Value = Environ("username")
LogRange(5).Value = Now

Next idxCols

Next idxRows

.Columns("A:E").AutoFit

End With

Application.EnableEvents = True

End Sub

Private Sub Workbook_SheetSelectionChange(ByVal Sh As Object, ByVal Target As Range)
oldValues = Target.Formula
End Sub


This has the weakness that when a user copies multiple cells and then selects a single cell and pastes, it will error out, due to mismatching indices. (It works when you copy, e.g. 3 cells in a row, then select 3 other cells in a row and paste.) Not sure how to avoid that. We'd need to capture the size of the pasted range to update oldValues accordingly. As Excel doesn't expose a Workbook_SheetBeforePaste event, that seems rather tricky.







share|improve this answer














share|improve this answer



share|improve this answer








edited Nov 23 '18 at 16:23

























answered Nov 21 '18 at 10:44









InarionInarion

473212




473212













  • Sorry for late response @Inarion, I have assignment these 2 days, really sorry for late. i have tested your code, but when i input something in a black cell, it shows me the error. "type mismatch", what's wrong with it?

    – Nicawong9147
    Nov 26 '18 at 3:51













  • @Nicawong9147 I'm not sure what a cell's color has to do with any of this? Can you make sure there's no other property of that cell that could be the culprit?

    – Inarion
    Nov 27 '18 at 16:39











  • Sorry, Wrong typing, should be blank cell, not black cell.i put your code in the Thisworkbook and build the LogDetails sheet. No matter what i am input in Sheet1, Sheet2 or Sheet3, just show me the type mismatch.

    – Nicawong9147
    Nov 29 '18 at 1:19











  • The error code show in this code: LogRange(2).Value = "'" & oldValues(idxRows, idxCols)

    – Nicawong9147
    Nov 29 '18 at 1:22



















  • Sorry for late response @Inarion, I have assignment these 2 days, really sorry for late. i have tested your code, but when i input something in a black cell, it shows me the error. "type mismatch", what's wrong with it?

    – Nicawong9147
    Nov 26 '18 at 3:51













  • @Nicawong9147 I'm not sure what a cell's color has to do with any of this? Can you make sure there's no other property of that cell that could be the culprit?

    – Inarion
    Nov 27 '18 at 16:39











  • Sorry, Wrong typing, should be blank cell, not black cell.i put your code in the Thisworkbook and build the LogDetails sheet. No matter what i am input in Sheet1, Sheet2 or Sheet3, just show me the type mismatch.

    – Nicawong9147
    Nov 29 '18 at 1:19











  • The error code show in this code: LogRange(2).Value = "'" & oldValues(idxRows, idxCols)

    – Nicawong9147
    Nov 29 '18 at 1:22

















Sorry for late response @Inarion, I have assignment these 2 days, really sorry for late. i have tested your code, but when i input something in a black cell, it shows me the error. "type mismatch", what's wrong with it?

– Nicawong9147
Nov 26 '18 at 3:51







Sorry for late response @Inarion, I have assignment these 2 days, really sorry for late. i have tested your code, but when i input something in a black cell, it shows me the error. "type mismatch", what's wrong with it?

– Nicawong9147
Nov 26 '18 at 3:51















@Nicawong9147 I'm not sure what a cell's color has to do with any of this? Can you make sure there's no other property of that cell that could be the culprit?

– Inarion
Nov 27 '18 at 16:39





@Nicawong9147 I'm not sure what a cell's color has to do with any of this? Can you make sure there's no other property of that cell that could be the culprit?

– Inarion
Nov 27 '18 at 16:39













Sorry, Wrong typing, should be blank cell, not black cell.i put your code in the Thisworkbook and build the LogDetails sheet. No matter what i am input in Sheet1, Sheet2 or Sheet3, just show me the type mismatch.

– Nicawong9147
Nov 29 '18 at 1:19





Sorry, Wrong typing, should be blank cell, not black cell.i put your code in the Thisworkbook and build the LogDetails sheet. No matter what i am input in Sheet1, Sheet2 or Sheet3, just show me the type mismatch.

– Nicawong9147
Nov 29 '18 at 1:19













The error code show in this code: LogRange(2).Value = "'" & oldValues(idxRows, idxCols)

– Nicawong9147
Nov 29 '18 at 1:22





The error code show in this code: LogRange(2).Value = "'" & oldValues(idxRows, idxCols)

– Nicawong9147
Nov 29 '18 at 1:22




















draft saved

draft discarded




















































Thanks for contributing an answer to Stack Overflow!


  • Please be sure to answer the question. Provide details and share your research!

But avoid



  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.


To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53409158%2fcreate-log-history-for-a-cell-value-change-in-a-column%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

"Incorrect syntax near the keyword 'ON'. (on update cascade, on delete cascade,)

Alcedinidae

Origin of the phrase “under your belt”?