Auto Update Timestamp in Excel - excel

I'm currently working on a sheet that has to automatically insert todays date in a cell, if another cell is = "Yes"
I currently have this line of code (that I found online):
Private Sub Worksheet_Change(ByVal Target As Range)
Dim cell As Range
If Not Intersect(Target, Range("G:G")) Is Nothing Then
Application.EnableEvents = False
For Each cell In Target
cell.Offset(0, 4).Value = Now
cell.Offset(0, 4).NumberFormat = "dd/mm/yyyy"
Next cell
End If
Application.EnableEvents = True
End Sub
The problem is that the updated cell in row K is being updated every time the cell is changed, and it should only be updated when the cell in row G = "Yes"
I appreciate the help :)

Your basic problem is solved easily - just add an If to check the content of the cell:
For Each cell In Target
If UCase(cell.Value2) = "YES" Then
cell.Offset(0, 4).Value = Now
cell.Offset(0, 4).NumberFormat = "dd/mm/yyyy"
Next cell
Next cell
However, your check for column 'G' is flawed. Target contains all cells that are currently modified. If the user enter something into a cell, Target will contain exactly that cell. If, however, data is for example pasted into that sheet, Target will contain all cells where data is pasted into.
Now, Intersect checks if two ranges have common cells. Your statement If Not Intersect(Target, Range("G:G")) Is Nothing will check if any of the modified cells is in column G and if yes, it will write the date into the cell that is 4 columns to the right. In the case the user enter something into a cell of column G, that's okay. But if he pastes something into, let's say, cells of columns F,G,H, the code will run for all three cells. So you should check each cell individually.
Private Sub Worksheet_Change(ByVal Target As Range)
On Error GoTo change_exit ' Ensure that events are re-enabled in case of error
Application.EnableEvents = False
Dim cell As Range
For Each cell In Intersect(Target, Range("G:G"))
If UCase(cell.Value2) = "YES" Then
cell.Offset(0, 4).Value = Now
cell.Offset(0, 4).NumberFormat = "dd/mm/yyyy"
end if
Next cell
change_exit:
Application.EnableEvents = True
End Sub
Update: Changed the logic by just looping over the cells of target that intersect with column G - thanks to BigBen for the hint.

Consider:
Private Sub Worksheet_Change(ByVal Target As Range)
Dim cell As Range
If Not Intersect(Target, Range("G:G")) Is Nothing Then
Application.EnableEvents = False
For Each cell In Target
If cell.Value = "Yes" Then
cell.Offset(0, 4).Value = Now
cell.Offset(0, 4).NumberFormat = "dd/mm/yyyy"
End If
Next cell
End If
Application.EnableEvents = True
End Sub
We test the value of each entry!

Related

Update cell protection based on another cell's value

I am trying to track data in a laboratory.
Goal. When the value in cell P3 changes to "yes", then cells Q3:AE3 are locked. However, if "yes" does not appear in cell P3, then cells Q3:AE3 are unlocked.
I need to loop through column P locking/unlocking cells with respect to the row each P value is located.
For example if P36 = "Yes", the Q36:AE36 would become locked.
Edit: This code works with line P3. How can I make this loop through P3:P500?
Private Sub Worksheet_Change(ByVal Target As Range)
If Range("P3") = "Yes" Then
Range("Q3:AE3").Locked = True
ElseIf Range("P3") = "No" Then
Range("Q3:AE3").Locked = False
ElseIf Range("P3") = "" Then
Range("Q3:AE3").Locked = False
End If
End Sub
This will handle any number of values being changed in column P. Provide your password as needed.
Option Explicit
Private Sub Worksheet_Change(ByVal Target As Range)
'did any cells in column P change
If Not Intersect(Target, Me.Range("P1").EntireColumn) Is Nothing Then
Me.Unprotect "password"
Dim cell As Range
For Each cell In Intersect(Target, Me.Range("P1").EntireColumn)
Me.Range("Q" & cell.Row & ":AE" & cell.Row).Locked = UCase$(cell.Value) = "YES"
Next
Me.Protect "password"
End If
End Sub

Accumulating values that are input into single Excel cell

I'm trying to create a cell in Excel that resets every time I put a value into it and every value that I put in the cell is stored and added together.
So basically cell A1 would be empty and then I add a value 30, for example. The cell would then store that value and reset to receive more inputs. I then go ahead and put another value in cell A1, 20. The cell should once again reset, but the value stored in cell A1 would now be equal to 50.
I'm very new to VBA so I'm still trying to figure everything out. I tried using some code I found in another post, but was not able to make it work so I was wondering if anyone had any idea on how to proceed with this problem.
This is the code I found and wasn't able to make it work. It was supposed to receive a value in cell A1 and store the same in cell A2, and once you add a new value to A1, it adds it to the previous value in A2.
Private Sub Worksheet_Change(ByVal Target As Range)
If Cells(1, 1).Value <> gdDouble Then
gdDouble = Cells(1, 1).Value
Cells(2, 1).Value = Cells(2, 1).Value + Cells(1, 1).Value
End If
End Sub
Private Sub Workbook_Open()
gdDouble = Sheets("sheet1").Cells(1, 1).Value
End Sub
And in the standard module:
dim gdDouble as double
Thank you
Adjust the code in the worksheet_change event like that
Private Sub Worksheet_Change(ByVal Target As Range)
If Intersect(Target, Range("A1")) Is Nothing Then Exit Sub
'If Target.CountLarge > 1 Then Exit Sub
On Error GoTo EH
Application.EnableEvents = False
Target.Value = Target.Value + gdDouble
gdDouble = Target.Value
EH:
Application.EnableEvents = True
End Sub
And change gdDouble to a public variable
Public gdDouble As Double

Add value in all cells within a column to corresponding cell in another column and then clear original cells

I need to create an Excel document with updating totals in the A column, based on numbers entered in the B column. Each respective cell in row A should update based on its equivalent B cell value whenever a new value is added, and then the value entered into B is cleared once added to A.
I have gotten things working for one single row but don't have knowledge or understanding on how to best make this work for EACH cell pair in the entire column. I really don't want to copy and paste this 10,000 times and update the cells to reference the correct pair. Code for single cell:
Private bIgnoreEvent As Boolean
Private Sub Worksheet_Change(ByVal Target As Range)
If bIgnoreEvent Then Exit Sub
bIgnoreEvent = True
Cells(1, 2) = Cells(1, 2) + Cells(1, 1)
Cells(1, 1) = ""
bIgnoreEvent = False
End Sub
I am hoping this can be achieved with a loop function, or a range of some sort.
This should work:
Private Sub Worksheet_Change(ByVal Target As Range)
Dim rng As Range, c As Range
'any updates in ColB?
Set rng = Application.Intersect(Target, Me.Columns(2))
If Not rng Is Nothing Then
Application.EnableEvents = False '<< prevent re-triggering of event
'Process each updated cell
For Each c In rng
If IsNumeric(c.Value) Then
With c.Offset(0, -1)
.Value = .Value + c.Value
End With
c.ClearContents
End If
Next c
Application.EnableEvents = True '<< re-enable event
End If
End Sub

EXCEL VBA: Format existing numeric cells based on value range

Am trying to run VBA on certain columns (ex: M, N, U, V...) to format the values based on their range.
I currently have:
Private Sub Worksheet_Change(ByVal Target As Range)
If Not Intersect(Target, Range("U:W")) Is Nothing Then
If Target.Value < -1000000 Then
Target.NumberFormat = "#,###.0,, ""M"""
ElseIf Target.Value <= -1000 Then
Target.NumberFormat = "#,###.0, ""K"""
ElseIf Target.Value < 1000 Then
Target.NumberFormat = "### """""
ElseIf Target.Value < 1000000 Then
Target.NumberFormat = "#,###.0, ""K"""
ElseIf Target.Value < 1000000000 Then
Target.NumberFormat = "#,###.0,, ""M"""
ElseIf Target.Value < 1000000000000# Then
Target.NumberFormat = "#,###.0,,, ""B"""
End If
End If
End Sub
Unfortunately, this isn't working on values already entered. However, if I click in each cell and then hit return, if formats correctly.
QUESTION: How would I go about formatting the values that are already there?
Thank you
Looks like the Target is only the range that changed:
https://msdn.microsoft.com/en-us/vba/excel-vba/articles/worksheet-change-event-excel
You'll probably have to write a sub that will loop through the other data, or just "edit" the cells once and the macro will work going forward.
EDIT:
How about looping through the columns and calling your function?:
Sub OneTimeLoop()
Dim rng as Range, cell as Range
set rng = Range("U:V")
For Each cell in rng
Worksheet_Change cell
Next cell
End Sub
I think, you need Precedents property, which will retrieve all cells a current cell is dependent upon.
Say, you have:
in A1 cell: 1
in A2 cell: =A1+1
Then the following code will show $A$1:
Sub F()
MsgBox Range("A2").Precedents(1).Address
End Sub

Update cell when selected

I need the active cell to have automatically the actual year as soon as a cell in the range A2:A20 is selected. My VBA code changes all the cells at once.
Private Sub Worksheet_Change(ByVal Target As Range)
Dim i As Integer
For i = 2 To 20
If ActiveCell = Cells(i, "A") And Cells(i, "A") = "" Then
Cells(i, "A").Value = Year(Now)
End If
Next i
Range("A:A").EntireColumn.AutoFit
End Sub
Since you want that A2:A20 to have the current year, automatically when the cell is selected, you need to use the Worksheet_SelectionChange event. Then, in that event, you simply test if the cell that was selected is within the A2:A20 range and set the value to the current year if it is.
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
If Not Intersect(Me.Range("A2:A20"),Target) Is Nothing Then
Target.Value = Year(Now())
End If
Range("A:A").EntireColumn.AutoFit
End Sub

Resources