Copy filtered rows from worksheet to the last row of another worksheet - excel

I've been working on adapting our excel based sales report into an in-house CRM using macros.
This is the macro I've managed to get to work using code found on this site :
Option Explicit
Private Sub Worksheet_Change(ByVal Target As Range)
If Not Intersect(Target, Columns(10), Me.UsedRange.Offset(1, 0)) Is Nothing Then
On Error GoTo bm_Safe_Exit
Application.EnableEvents = False
End If
Dim xCellColumn As Integer
Dim xTimeColumn As Integer
Dim xRow, xCol As Integer
Dim xDPRg, xRg As Range
xCellColumn = 10
xTimeColumn = 11
xRow = Target.Row
xCol = Target.Column
If Target.Text <> "" Then
If xCol = xCellColumn Then
Cells(xRow, xTimeColumn) = Now
Else
On Error Resume Next
Set xDPRg = Target.Dependents
For Each xRg In xDPRg
If xRg.Column = xCellColumn Then
Cells(xRg.Row, xTimeColumn) = Now
End If
Next
End If
Dim a As Range
For Each a In Intersect(Target, Columns(10), Me.UsedRange.Offset(1, 0))
If CBool(Len(a.Value2)) Then _
a.EntireRow.Copy _
Destination:=Sheet3.Cells(Rows.Count, 1).End(xlUp).Offset(1, 0)
Next a
End If
bm_Safe_Exit:
Application.EnableEvents = True
End Sub
This works great for our basic needs but whenever an opportunity closes, we'd like it to be transferred below the existing data to 3 separate worksheets based on the result of the opportunity (Won, Lost, Renewed) and removed from the main CRM sheet (aka cut and not copy). Those values being some of the choices in column 10, the same row used in my script above.
There's a myriad of different scripts around to accomplish some portion of what I want but I unfortunately couldn't get any script I've tried to work on my file, much less work as intended since our situation involves a few different "special" use case (no filters, multiple criterias, existing tables to receive data, etc).
Basically I'm looking to add on to the script above so :
all rows are still be copied to the Log sheet (Sheet 3)
when an entry matching either Won, Lost or Renewed is selected, that entire row should be cut from the CRM sheet (Sheet 1)
That row should be pasted below the existing data in either sheet 2 (won), sheet 5 (lost) and sheet 6 (renewed)
Any help or advice would be more than appreciated.
Thanks.
Edit :
I've continued to work on getting this to work and I managed to get it to work.
But when I cut the row, it also cuts away the formatting of the row including data validation. Is there any way to cut the data but leave formatting and data validation settings intact ? Perhaps trough the use of special paste ?
Here's the code I used :
Option Explicit
Private Sub Worksheet_Change(ByVal Target As Range)
If Not Intersect(Target, Columns(10), Me.UsedRange.Offset(1, 0)) Is Nothing Then
On Error GoTo bm_Safe_Exit
Application.EnableEvents = False
End If
Dim xCellColumn As Integer
Dim xTimeColumn As Integer
Dim xRow, xCol As Integer
Dim xDPRg, xRg As Range
xCellColumn = 10
xTimeColumn = 11
xRow = Target.Row
xCol = Target.Column
If Target.Text <> "" Then
If xCol = xCellColumn Then
Worksheets("CRM").Cells(xRow, xTimeColumn) = Now
Else
On Error Resume Next
Set xDPRg = Target.Dependents
For Each xRg In xDPRg
If xRg.Column = xCellColumn Then
Worksheets("CRM").Cells(xRg.Row, xTimeColumn) = Now
End If
Next
End If
Dim a As Range
For Each a In Intersect(Target, Columns(10), Me.UsedRange.Offset(1, 0))
If CBool(Len(a.Value2)) Then _
a.EntireRow.Copy _
Destination:=Sheet3.Cells(Rows.Count, 1).End(xlUp).Offset(1, 0)
Next a
End If
For Each a In Intersect(Target, Columns(10), Me.UsedRange.Offset(1, 0))
If Target.Value = "Closed Won" Then _
a.EntireRow.Cut _
Destination:=Sheet2.Cells(Rows.Count, 1).End(xlUp).Offset(1, 0)
Sheets("CRM").Rows(10000).EntireRow.Copy
ActiveCell.EntireRow.Paste
Next a
For Each a In Intersect(Target, Columns(10), Me.UsedRange.Offset(1, 0))
If Target.Value = "Closed Lost" Then _
a.EntireRow.Cut _
Destination:=Sheet5.Cells(Rows.Count, 1).End(xlUp).Offset(1, 0)
Next a
For Each a In Intersect(Target, Columns(10), Me.UsedRange.Offset(1, 0))
If Target.Value = "Renewal" Then _
a.EntireRow.Cut _
Destination:=Sheet6.Cells(Rows.Count, 1).End(xlUp).Offset(1, 0)
Next a
bm_Safe_Exit:
Application.EnableEvents = True
End Sub

Finally managed to it to work like I wanted.
Here's the code for anyone else this might help.
The first part inserts the date when a cell is modified.
Second part copies to data to the log page
Third part copies the data to the right tab if it meats the specified criteria and deletes the row from the CRM page.
Option Explicit
Private Sub Worksheet_Change(ByVal Target As Range)
If Not Intersect(Target, Columns(10), Me.UsedRange.Offset(1, 0)) Is Nothing Then
On Error GoTo bm_Safe_Exit
Application.EnableEvents = False
End If
Dim xCellColumn As Integer
Dim xTimeColumn As Integer
Dim xRow, xCol As Integer
Dim xDPRg, xRg As Range
xCellColumn = 10
xTimeColumn = 11
xRow = Target.Row
xCol = Target.Column
If Target.Text <> "" Then
If xCol = xCellColumn Then
Worksheets("CRM").Cells(xRow, xTimeColumn) = Now
Else
On Error Resume Next
Set xDPRg = Target.Dependents
For Each xRg In xDPRg
If xRg.Column = xCellColumn Then
Worksheets("CRM").Cells(xRg.Row, xTimeColumn) = Now
End If
Next
End If
Dim a As Range
For Each a In Intersect(Target, Columns(10), Me.UsedRange.Offset(1, 0))
If CBool(Len(a.Value2)) Then _
a.EntireRow.Copy _
Destination:=Sheet3.Cells(Rows.Count, 1).End(xlUp).Offset(1, 0)
Next a
End If
For Each a In Intersect(Target, Columns(10), Me.UsedRange.Offset(1, 0))
If Target.Value = "Closed Won" Then _
a.EntireRow.Copy _
Destination:=Sheet2.Cells(Rows.Count, 1).End(xlUp).Offset(1, 0)
Next a
For Each a In Intersect(Target, Columns(10), Me.UsedRange.Offset(1, 0))
If Target.Value = "Closed Won" Then _
a.EntireRow.Delete
Next a
For Each a In Intersect(Target, Columns(10), Me.UsedRange.Offset(1, 0))
If Target.Value = "Closed Lost" Then _
a.EntireRow.Copy _
Destination:=Sheet5.Cells(Rows.Count, 1).End(xlUp).Offset(1, 0)
Next a
For Each a In Intersect(Target, Columns(10), Me.UsedRange.Offset(1, 0))
If Target.Value = "Closed Lost" Then _
a.EntireRow.Delete
Next a
For Each a In Intersect(Target, Columns(10), Me.UsedRange.Offset(1, 0))
If Target.Value = "Renewal" Then _
a.EntireRow.Copy _
Destination:=Sheet6.Cells(Rows.Count, 1).End(xlUp).Offset(1, 0)
Next a
For Each a In Intersect(Target, Columns(10), Me.UsedRange.Offset(1, 0))
If Target.Value = "Renewal" Then _
a.EntireRow.Delete
Next a
bm_Safe_Exit:
Application.EnableEvents = True
End Sub

Related

Excel VBA dual Worksheet_change events not working

Having trouble executing both Worksheet_Change events correctly. Image below show my results, when modifying column B, column M does nothing. When modifying column L, column N updates as expected but only on row 2. Every other subsequent change to B or M results in N:2 updating to the current time again.
My desired outcome is that when Col B is updated I record a time stamp in Col M and the same when Col L updates that I get a time stamp in Col N.
Example of Excel Error
My current code is here:
Option Explicit
Private Sub Worksheet_Change(ByVal Target As Range)
Application.EnableEvents = False
Dim rng As Range
Dim rng2 As Range
If Not Intersect(Target, Columns("B"), Target.Parent.UsedRange) Is Nothing Then
On Error GoTo Safe_Exit
For Each rng In Intersect(Target, Columns("B"), Target.Parent.UsedRange)
If CBool(Len(rng.Value2)) And Not CBool(Len(rng.Offset(0, 11).Value2)) Then
rng.Offset(0, 11) = Now
ElseIf Not CBool(Len(rng.Value2)) And CBool(Len(rng.Offset(0, 11).Value2)) Then
rng.Offset(0, 11) = vbNullString
End If
Next rng
Application.EnableEvents = True
End If
ElseIf Not Intersect(Target, Columns("L"), Target.Parent.UsedRange) Is Nothing Then
On Error GoTo Safe_Exit
For Each rng2 In Intersect(Target, Columns("L"), Target.Parent.UsedRange)
If CBool(Len(rng2.Value2)) And Not CBool(Len(rng2.Offset(0, 2).Value2)) Then
rng2.Offset(0, 2) = Now
ElseIf Not CBool(Len(rng2.Value2)) And CBool(Len(rng2.Offset(0, 2).Value2)) Then
rng2.Offset(0, 2) = vbNullString
End If
Next rng2
Application.EnableEvents = True
End If
Safe_Exit:
End Sub
Mock-up, untested, change of code to simplify as you're doing the same actions in two spots:
Option Explicit
Private Sub Worksheet_Change(ByVal Target As Range)
Application.EnableEvents = False
Dim columnLetter as String
Select Case Target.Column
Case 2 'B
columnLetter = "M"
Case 12 'L
columnLetter = "N"
Case Else
Goto Safe_Exit
End Select
Dim loopRng as Range
For Each loopRng In Range(Cells(Target.Row, Target.Column),Cells(Target.End(xlDown).Row,Target.Column)
If IsEmpty(loopRng) = True And IsEmpty(Cells(loopRng.Row,columnLetter)) = False Then
Cells(loopRng.Row,columnLetter) = Now
ElseIf IsEmpty(loopRng) = False And IsEmpty(Cells(loopRng.Row,columnLetter)) = True Then
Cells(loopRng.Row,columnLetter) = vbNullString
End If
Next loopRng
'Columns(columnLetter).NumberFormat = "yyyy/mm/dd"
Application.EnableEvents = True
Safe_Exit:
Application.EnableEvents = True
End Sub
Note that the IsEmpty() = True is important... when using an If case, you need to specify for each condition, otherwise the implicit detection will fail.
Edit1: Removed Intersect from loop, whereas the range i've listed will need corrected... it at least references a specific range, now.
Edit2: Removing .Offset and working with specific column references in cells().
I tried this version of my original code and it started to work for some reason.
Option Explicit
Private Sub Worksheet_Change(ByVal Target As Range)
If Not Intersect(Target, Columns("B"), Target.Parent.UsedRange) Is Nothing Then
On Error GoTo Safe_Exit
Application.EnableEvents = False
Dim rng As Range
For Each rng In Intersect(Target, Columns("B"), Target.Parent.UsedRange)
If CBool(Len(rng.Value2)) And Not CBool(Len(rng.Offset(0, 11).Value2)) Then
rng.Offset(0, 11) = Now
ElseIf Not CBool(Len(rng.Value2)) And CBool(Len(rng.Offset(0, 11).Value2)) Then
rng.Offset(0, 11) = vbNullString
End If
Next rng
End If
If Not Intersect(Target, Columns("L"), Target.Parent.UsedRange) Is Nothing Then
On Error GoTo Safe_Exit
Application.EnableEvents = False
For Each rng In Intersect(Target, Columns("L"), Target.Parent.UsedRange)
If CBool(Len(rng.Value2)) And Not CBool(Len(rng.Offset(0, 2).Value2)) Then
rng.Offset(0, 2) = Now
ElseIf Not CBool(Len(rng.Value2)) And CBool(Len(rng.Offset(0, 2).Value2)) Then
rng.Offset(0, 2) = vbNullString
End If
Next rng
End If
Safe_Exit:
Application.EnableEvents = True
End Sub

Figuring Out the Multiple Worksheet Change Function

I've read through a bunch of similar questions, but I'm honestly not quite understanding the solution. I've changed the code, and essentially seem to have broken it even more.
Expectation: When the data in the E column is changed, the L and M columns will erase themselves. Additionally, if the F column = "DFW" then it will copy/paste the row to the DFW sheet, and then delete and move up the original row from Sheet1.
Current Result: Nothing happening. Before I added the If Nots (which were suggested in previous posts), I would get the functions to work once, but it would have a weird hangtime but work once. After that, I'd have to restart the spreadsheet to get everything to function again.
Bonus: If there is also a way to auto sort based on column N (oldest to newest) and then sub sort based on column A (A to Z). Essentially organize by date, and then those entries organized alphabetically.
Thanks in advance for any help!
Sub Worksheet_Change(ByVal Target As Range)
Dim tbl As ListObject
Dim i As Long
' Exit if more than one cell updated
' If Target.CountLarge > 1 Then Exit Sub
' Check to see if row > 1 and value is "Yes"
' If (Target.Row > 2) And (Target.Value = "DFW") Then
If Not Intersect(Target, Range("F:F")) Is Nothing Then
If Target.Value = "DFW" Then
' Set tbl to new table
Set tbl = Sheets("DFW").ListObjects("Tasks7835")
' Add row
tbl.ListRows.Add , 1
' set i to rowcount of table
i = tbl.ListRows.Count
' copy values
tbl.DataBodyRange(i, 1).Resize(1, 20).Value = Range("A" & Target.Row).Resize(1, 20).Value
Application.EnableEvents = False
' Delete old row
Target.EntireRow.Delete Shift:=xlUp
Application.EnableEvents = True
Exit Sub
End If
' If Target.Cells.Count > 1 Then Exit Sub
' If Intersect(Target, Range("E:E")) Is Nothing Then Exit Sub
If Not Intersect(Target, Range("E:E")) Is Nothing Then
Application.EnableEvents = False
If Target = vbNullString Then
Target.Offset(0, 7) = vbNullString
Target.Offset(0, 8) = vbNullString
Else
Target.Offset(0, 7) = ""
Target.Offset(0, 8) = ""
End If
On Error GoTo 0
End Sub
Try this code:
Option Explicit
Sub Worksheet_Change(ByVal Target As Range)
Dim TCELL As Range
On Error GoTo out
Application.EnableEvents = False
Set TCELL = Intersect(Target, Me.Columns("F"))
If Not TCELL Is Nothing Then
Set TCELL = TCELL(1) ' get only first cell from Target
If UCase(TCELL) = "DFW" Then
ThisWorkbook.Sheets("DFW").ListObjects("Tasks7835") _
.ListRows.Add(, True).Range.Resize(1, 20).Value = _
Me.Range("A" & TCELL.Row).Resize(1, 20).Value
TCELL.EntireRow.Delete
End If
Else
Set TCELL = Intersect(Target, Me.Columns("E"))
If Not TCELL Is Nothing Then
TCELL(1).Offset(0, 7).Resize(, 2) = vbNullString
End If
End If
out:
Application.EnableEvents = True
End Sub
The original code was almost workable. It was missing two End If. Also, Application.EnableEvents = True was omitted from the second part of the procedure. I also removed some redundant commands such as On Error GoTo 0, Target.Offset(0, 7) = "", i = tbl.ListRows.Count. In addition, I introduced a TCELL variable containing one cell (Target can contain multiple cells and in this case throw an error when executing If Target.Value = ... Then)
A Worksheet Change: Backup Before Delete
Option Explicit
Sub Worksheet_Change(ByVal Target As Range)
Const FirstRow As Long = 2
Dim srg As Range
Dim irg As Range
Set srg = Me.Columns("E").Resize(Me.Rows.Count - FirstRow + 1)
Set irg = Intersect(srg, Target)
If Not irg Is Nothing Then
Application.EnableEvents = False
Intersect(irg.EntireRow, Me.Columns("L:M")).ClearContents
Application.EnableEvents = True
Set irg = Nothing
End If
Set srg = Me.Columns("F").Resize(Me.Rows.Count - FirstRow + 1)
Set irg = Intersect(srg, Target)
If Not irg Is Nothing Then
Dim tbl As ListObject
Set tbl = Me.Parent.Worksheets("DFW").ListObjects("Tasks7835")
Dim drg As Range
Dim iCell As Range
Dim lr As ListRow
For Each iCell In irg.Cells
If CStr(iCell.Value) = "DFW" Then
Set lr = tbl.ListRows.Add(, True)
lr.Range.Resize(, 20).Value = iCell.EntireRow.Resize(, 20).Value
If drg Is Nothing Then
Set drg = iCell
Else
Set drg = Union(drg, iCell)
End If
End If
Next iCell
If Not drg Is Nothing Then
Application.EnableEvents = False
drg.EntireRow.Delete xlShiftUp
Application.EnableEvents = True
End If
End If
End Sub

Log changes in Excel spreadsheet using VBA

I have the following problem. I need to log changes in a spreadsheet. My range goes from A1:M300000.
So far I have managed to log the address of the changed cell, the user, the old value, and the new value.
Now I would like to insert the following functions and need help. It's the first time I come into contact with VBA:
I also want my log file to show the value of a cell in another column. So I know which object it is. Example change cell B26 and now also A26 should be displayed in the log file.
Furthermore, I also want to log when new cells are inserted or existing records are deleted.
Here is my VBA code:
Option Explicit
Dim mvntWert As Variant
Private Sub Worksheet_Change(ByVal Target As Range)
Dim wks As Worksheet
Dim lngLast As Long
Set wks = Worksheets("Protokoll")
lngLast = wks.Range("A65536").End(xlUp).Row + 1
If Target.Count > 1 Then Exit Sub
If Intersect(Range("A1:M65536"), Target) Is Nothing Then Exit Sub
With wks
.Range("A" & lngLast).Value = Target.Address(0, 0)
.Range("B" & lngLast).Value = mvntWert
.Range("C" & lngLast).Value = Target.Value
.Range("D" & lngLast).Value = VBA.Environ("Username")
.Range("E" & lngLast).Value = Now
End With
End Sub
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
If Target.Count > 1 Then Exit Sub
If Intersect(Range("A1:M65536"), Target) Is Nothing Then Exit Sub
mvntWert = Target.Value
End Sub
I hope someone can help me. Thank you very much in advance.
greeting
ironman
Please, try the next code, I prepared yesterday for somebody else asking for a similar issue. It needs only one event and should do what you require here:
Private Sub Worksheet_Change(ByVal Target As Range)
Dim RangeValues As Variant, r As Long, boolOne As Boolean, TgValue 'the array to keep Target values (before UnDo)
Dim sh As Worksheet: Set sh = Worksheets("Protokoll")
Dim UN As String: UN = Application.userName
'sh.Unprotect "" 'it should be good to protect the sheet
If sh.Range("A1") = "" Then sh.Range("A1").Resize(1, 6) = _
Array("Time", "User Name", "Changed cell", "From", "To", "Sheet Name")
Application.ScreenUpdating = False 'to optimize the code (make it faster)
Application.Calculation = xlCalculationManual
If Target.cells.count > 1 Then
TgValue = extractData(Target)
Else
TgValue = Array(Array(Target.value, Target.Address(0, 0))) 'put the target range in an array (or as a string for a single cell)
boolOne = True
End If
Application.EnableEvents = False 'avoiding to trigger the change event after UnDo
Application.Undo
RangeValues = extractData(Target) 'define the RangeValue
putDataBack TgValue, ActiveSheet 'put back the changed data
If boolOne Then Target.Offset(1).Select
Application.EnableEvents = True
Dim columnHeader As String, rowHeader As String
For r = 0 To UBound(RangeValues)
If RangeValues(r)(0) <> TgValue(r)(0) Then
sh.cells(rows.count, 1).End(xlUp).Offset(1, 0).Resize(1, 6).value = _
Array(Now, UN, RangeValues(r)(1), RangeValues(r)(0), TgValue(r)(0), Target.Parent.Name)
End If
Next r
'sh.Protect ""
Application.ScreenUpdating = True
Application.Calculation = xlCalculationAutomatic
End Sub
Sub putDataBack(arr, sh As Worksheet)
Dim i As Long, arrInt, El
For Each El In arr
sh.Range(El(1)).value = El(0)
Next
End Sub
Function extractData(rng As Range) As Variant
Dim a As Range, arr, count As Long, i As Long
ReDim arr(rng.cells.count - 1)
For Each a In rng.Areas 'creating a jagged array containing the values and the cells address
For i = 1 To a.cells.count
arr(count) = Array(a.cells(i).value, a.cells(i).Address(0, 0)): count = count + 1
Next
Next
extractData = arr
End Function

Update excel cell with date if a cell in a range is update

I need to update a cell with the date and time stamp (NOW()) if any cell is updated within any cell before it within that same row.
So update cell "CU" with date and time when any cell from "A-CR" is updated.
I have done some searching but I can only seem to find bits that work if only updating a single cell, I'm looking for if anything changes within that range.
I currently have some Vba which does something similar which will update the adjacent cell with time and date which is required but I also need an overall one for the whole process.
Private Sub Worksheet_Change(ByVal Target As Range)
If Not Intersect(Target, Range("F:F, I:I, L:L, O:O, R:R, U:U, X:X, AA:AA, AB:AB, AE:AE, AH:AH, AK:AK, AN:AN, AQ:AQ, AT:AT, AW:AW, AZ:AZ, BC:BC, BF:BF, BI:BI, BL:BL, BO:BO, BR:BR, BU:BU, BX:BX, CA:CA, CD:CD, CG:CG, CJ:CJ, CM:CM, CP:CP")) Is Nothing Then
On Error GoTo safe_exit
With Application
.EnableEvents = False
.ScreenUpdating = False
Dim trgt As Range, ws1 As Worksheet
'Set ws1 = ThisWorkbook.Worksheets("Info")
For Each trgt In Intersect(Target, Range("F:F, I:I, L:L, O:O, R:R, U:U, X:X, AA:AA, AB:AB, AE:AE, AH:AH, AK:AK, AN:AN, AQ:AQ, AT:AT, AW:AW, AZ:AZ, BC:BC, BF:BF, BI:BI, BL:BL, BO:BO, BR:BR, BU:BU, BX:BX, CA:CA, CD:CD, CG:CG, CJ:CJ, CM:CM, CP:CP"))
If trgt <> vbNullString Then
If UCase(trgt.Value) = "Y" Or UCase(trgt.Value) = "N" Then
Cells(trgt.Row, trgt.Column + 1) = Now()
Cells(trgt.Row, trgt.Column + 2) = Environ("username")
'Select Case trgt.Column
' Case 2 'column B
' Cells(trgt.Row, trgt.Column + 1) = Environ("username")
' Case 4 'column D
' 'do something else
' End Select
Else
trgt = ""
Cells(trgt.Row, trgt.Column + 1) = ""
Cells(trgt.Row, trgt.Column + 2) = ""
End If
End If
Next trgt
'Set ws1 = Nothing
End With
End If
safe_exit:
Application.EnableEvents = True
Application.ScreenUpdating = True
End Sub
This works for me:
Option Explicit
Private Sub Worksheet_Change(ByVal Target As Range)
Application.EnableEvents = False
If Intersect(Target, Me.Range("A" & Target.Row & ":CR" & Target.Row)) Is Nothing Then GoTo SafeExit
Me.Cells(Target.Row, "CU") = Now()
SafeExit:
Application.EnableEvents = True
End Sub
The below code takes care of:
Clearing the time if the row is blank.
Updating the time only if the values really change from the previous value.
Dim oldValue As String
'Change the range below where your data will be
Const RangeString = "A:CR"
'Below variable decides the column in which date will be displayed
'Change the below value to 1 for column A, 2 for B, ... 99 for CU
Const ColumnIndex = 99
Private Sub Worksheet_Change(ByVal Target As Range)
Dim WorkRng As Range
Dim HorizontalRng As Range
Dim Rng As Range
Dim HorRng As Range
Dim RowHasVal As Boolean
Set WorkRng = Intersect(ActiveSheet.Range(RangeString), Target)
If Not WorkRng Is Nothing Then
If WorkRng.Cells.Count = 1 And WorkRng.Cells(1, 1).Value = oldValue Then
Exit Sub
End If
Application.EnableEvents = False
For Each Rng In WorkRng
Set HorizontalRng = Intersect(ActiveSheet.Range(RangeString), Rows(Rng.Row))
RowHasVal = False
For Each HorRng In HorizontalRng
If Not VBA.IsEmpty(HorRng.Value) Then
RowHasVal = True
Exit For
End If
Next
If Not RowHasVal Then
ActiveSheet.Cells(Rng.Row, ColumnIndex).ClearContents
ElseIf Not VBA.IsEmpty(Rng.Value) Then
ActiveSheet.Cells(Rng.Row, ColumnIndex).Value = Now
ActiveSheet.Cells(Rng.Row, ColumnIndex).NumberFormat = "dd-mm-yyyy, hh:mm:ss"
End If
Next
Application.EnableEvents = True
End If
End Sub
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
If Not Intersect(Target, ActiveSheet.Range(RangeString)) Is Nothing Then
If Target.Cells.Count = 1 Then
oldValue = Target.Value
Else
oldValue = ""
End If
End If
End Sub

Count cell change individually

I have a little problem. I edited a code to count the cell changes for the selected cell what actually works great. This code goes into the sheets coding not as an individual macro to run.
How is possible to run the same code in parallel for different area counting separately from the other one watching different cells.
I tried with double IF what gave me an error and I tried the same code under different sub.
For the moment the code watching the C8 cells change and counts in D8.
I need to run another counter for C16 and to count in D18.
If I need to monitor multiple cells with separate counters how can I do it ?
Dim xCount As Integer
Private Sub Worksheet_Change(ByVal Target As Range)
Dim xRg As Range, xCell As Range
On Error Resume Next
If Target = Range("C8") Then
xCount = xCount + 1
Range("D8").Value = xCount
End If
Application.EnableEvents = False
Set xRg = Application.Intersect(Target.Dependents, Me.Range("C8"))
If Not xRg Is Nothing Then
xCount = xCount + 1
Range("D8").Value = xCount
End If
Application.EnableEvents = True
End Sub
EDITED:
Private Sub Worksheet_Change(ByVal Target As Range)
Dim xRg As Range, xCell As Range, ranges, x As Long
Dim deps As Range
If Target.Count > 1 Then Exit Sub '<<<<<<<< added this...
On Error GoTo haveError
ranges = Array("C8", "C16")
For x = 0 To UBound(ranges)
Set xCell = Range(ranges(x))
If Not Application.Intersect(Target, xCell) Is Nothing Then
Application.EnableEvents = False
xCell.Offset(0, 1).Value = xCell.Offset(0, 1).Value + 1
End If
Set deps = Nothing
On Error Resume Next 'suspend error trapping
Set deps = Target.Dependents
On Error GoTo haveError 'resume trapping
If Not deps Is Nothing Then
Set xRg = Application.Intersect(Target.Dependents, xCell)
If Not xRg Is Nothing Then
Application.EnableEvents = False
xCell.Offset(0, 1).Value = xCell.Offset(0, 1).Value + 1
End If
End If
Next x
haveError:
Application.EnableEvents = True
End Sub

Resources