Can I put several macros in one? - excel

I would like to create a sheet where I have rows that get a timestamp in the column next to it, if the content in the cell changes.
What do I do wrong in the following macro? The first macro works on its own, but not if I add several macros.
Sub Update01()
Sub Worksheet_Change(ByVal Target As Range)
If Target.Column <> 1 Then Exit Sub
If Target.Cells.Count > 1 Then Exit Sub
With Target.Offset(0, 1)
.Value = Now
.NumberFormat = "MM/DD/YYYY hh:mm AM/PM"
End With
End Sub
Sub Update02()
If Target.Column <> 3 Then Exit Sub
If Target.Cells.Count > 3 Then Exit Sub
With Target.Offset(0, 3)
.Value = Now
.NumberFormat = "MM/DD/YYYY hh:mm AM/PM"
End With
End
Sub Main()
Call Update01
Call Update02
End Sub

You probably meant to do something like the following
Sub Worksheet_Change(ByVal Target As Range)
If Target.Cells.Count > 1 Then Exit Sub
On Error Goto ENABLE_EVENTS
Application.EnableEvents = False
If Target.Column = 1 Then
With Target.Offset(0, 1)
.Value = Now
.NumberFormat = "MM/DD/YYYY hh:mm AM/PM"
End With
ElseIf Target.Column = 3
With Target.Offset(0, 3)
.Value = Now
.NumberFormat = "MM/DD/YYYY hh:mm AM/PM"
End With
End If
ENABLE_EVENTS:
Application.EnableEvents = True
End Sub
Note that you need to Application.EnableEvents = False before writing a value to a cell otherwise this would trigger the Worksheet_Change over and over again.
Also note that Worksheet_Change is an event. That means it runs automatically whenever a cell value in the worksheet gets changed. You cannot run this procedure manually and you cannot Call it.

Related

Worksheet_Change executed multiple times

I am using a MsgBox in an if else condition. When I use other conditions along with MsgBox, the MsgBox pops up multiple times and I have to end the program.
Code in a module:
Sub CheckValue(Target)
If Target.Offset(0, 12) < 1 Then
MsgBox "This is a sample box"
Range(Target.Offset(0, -12), Cells(Target.MergeArea(1, 1).Row, Target.MergeArea(1, 1).Offset(1, -2).Column)).ClearContents
Target.Offset(0, 0).ClearContents
Target.Offset(-4, 0).Select
End If
I activate this sub through worksheet change:
Private Sub Worksheet_Change(ByVal Target As Range)
If Target.Address = "$N$16" Then
Call CheckValue(Target)
End If
End Sub
As you clear contents in your CheckValue sub, you are triggering the change-event.
You have to add Application.EnableEvents
Sub CheckValue(Target)
If Target.Offset(0, 12) < 1 Then
MsgBox "This is a sample box"
Application.EnableEvents = false '--> disable event
Range(Target.Offset(0, -12), Cells(Target.MergeArea(1, 1).Row, Target.MergeArea(1, 1).Offset(1, -2).Column)).ClearContents
Target.Offset(0, 0).ClearContents
Application.EnableEvents = true '--> enable events
Target.Offset(-4, 0).Select
End If
end sub

if Cell is Blank then clear content of another cell Code in VBA

In My sheet when I update Cells in D column the Cell in C column will show date of update , now I need if I delete the info in D cell to Delete the info in C cell not as formula as VBA code
Code below :
`Private Sub Worksheet_Change(ByVal Target As Range)
If Target.Column <> 4 Then Exit Sub
If Target.Cells.Count > 1 Then Exit Sub
With Target.Offset(0, -1)
.Value = Now
.NumberFormat = " MM/DD/YY hh:mm Am/PM"
End With
Dim RangeA As Range
Set RangeA = Range("D10:D10000")
If Application.CountBlank(RangeA) = RangeA.Cells.Count Then
Range("C10:C10000").ClearContents
End If
End Sub`
I would recommend adding an if-statement to support your activities, such that:
Private Sub Worksheet_Change(ByVal Target As Range)
If Target.Column <> 4 Then Exit Sub
If Target.Cells.Count > 1 Then Exit Sub
If Target.Value <> "" then
With Target.Offset(0, -1)
.Value = Now
.NumberFormat = " MM/DD/YY hh:mm Am/PM"
End With
Else
Target.Offset(,-1).ClearContents
End If
End Sub

Disallow editing a cell once there is an entry

I am trying to build a log book where:
Once the operator enters information that cell should lock.
A date and time for the entry should auto populate.
I have tried several codes I found on bulletin boards, but nothing works.
Private Sub Worksheet_Change(ByVal Target As Range)
Dim i As Integer
Application.EnableEvents = False
If Target.Column = 2 Or Target.Column = 3 Then
For i = 2 To 1000
If Cells(i, "B").Value <> " " And Cells(i, "B").Value = " " Then
Cells(i, "A").Value = Date & " " & Time
Cells(i, "A").NumberFormat = "m/d/yyyy h:mm AM/PM"
End If
Next
End If
Range("F:F").EntireColumn.AutoFit
Application.EnableEvents = True
End Sub
In the same article you have a solution:
Private Sub Worksheet_Change(ByVal Target As Range)
If Not Intersect(Target, Range("B:B")) Is Nothing Then
On Error GoTo SafeExit
Application.EnableEvents = False
Dim bc As Range 'no sense in declaring something until we actually need it
For Each bc In Intersect(Target, Range("B:B")) 'deal with every cell that intersects. This is how to handle pastes into more than one cell
If Not IsEmpty(Cells(bc.Row, "B")) Then
Cells(bc.Row, "A").Value = Now 'Now is the equivalent of Date + Time
Cells(bc.Row, "A").NumberFormat = "m/d/yyyy h:mm AM/PM"
End If
Next bc
'Range("F:F").EntireColumn.AutoFit 'this slows things down. you may want to comment this out and just set an apprpriate column width that will handle everything
End If
SafeExit:
Application.EnableEvents = True
End Sub
I just addpat for your case on Range B:B.
Hope it helps

VBA Modify Insert Date Macro

There's a lot I like about this script I use to auto-insert the date into next cell over from where I input a value, but I would like if it didn't change a date that already existed.
When I input the initials of whoever finished a job into a cell in range T3:T5003, the date is automatically inserted in the adjacent cell in range U3:U5003. The problem is that I might have to change or modify the entries in T3:T5003 at a later date, but I don't want the original date to change. So I just want this auto-inserting to work only when there is nothing in the adjacent cell.
Here's the code I am using:
Private Sub Worksheet_Change(ByVal Target As Excel.Range)
With Target
If .Count > 1 Then Exit Sub
If Not Intersect(Range("T3:T5003"), .Cells) Is Nothing Then
Application.EnableEvents = False
If IsEmpty(.Value) Then
.Offset(0, 1).Activate
Else
With .Offset(0, 1)
.Value = Date
End With
End If
Application.EnableEvents = True
End If
End With
End Sub
I've tried other scripts that didn't write over an existing date, but they had other problems, and they were difficult for me to understand how they work, so I'm hoping that we can just modify the one I'm using. But I will take anything that works and I really appreciate your help.
I think you just need to an IF checking if the cell to the right is empty or not:
Private Sub Worksheet_Change(ByVal Target As Excel.Range)
With Target
If .Count > 1 Then Exit Sub
If Not Intersect(Range("A1:A100"), .Cells) Is Nothing Then
Application.EnableEvents = False
If IsEmpty(.Value) Then
.Offset(0, 1).Activate
Else
If .Offset(0, 1).Value2 = "" Then
With .Offset(0, 1)
.Value = Date
End With
End If
End If
Application.EnableEvents = True
End If
End With
End Sub
This should do
Private Sub Worksheet_Change(ByVal Target As Excel.Range)
With Target
If .Count > 1 Then Exit Sub
If Not Intersect(Range("T3:T5003"), .Cells) Is Nothing Then
If IsEmpty(.Offset(0, 1)) Then .Offset(0, 1).Value = Date
End If
End With
End Sub

excel Worksheet_SelectionChange - copying data

Scenario:
I have two worksheets the same except for "some content" in Sheet2 column C-E, and Sheet1 containing a Worksheet_SelectionChange handler
When I click on column B in Sheet1 the Worksheet_SelectionChange changes the cell colour and then sets column C-E to that of Sheet2 Column C
Problem:
Trouble is it falls over on an application error...
Can anyone help please, this is really annoying...just how do i copy the data from Sheet2 to Sheet 1 in a Worksheet_SelectionChange handler?
If I set S1C = "X" (as in hardcoded it's fine), its when I try to reference the cell from the second sheet that it doesn't work.
many thanks in advance,
Best regards
Code as follows:
Public benRel
Public rskOpt
Public resOpt
Public getRow
Public getCol
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
On Error GoTo ExitSubCorrectly
'turn off multiple recurring changes
Application.EnableEvents = False
'do not allow range selection
If Target.Cells.Count > 1 Then GoTo ExitSubCorrectly
'only allow selection within our range
Set myRange = Range("B8:B24")
If Not Application.Intersect(Target, myRange) Is Nothing Then
' At least one cell of Target is within the range myRange.
' Carry out some action.
getRow = Target.Row
getCol = Target.Column
Select Case Range(Cells(Target.Row, Target.Column), Cells(Target.Row, Target.Column)).Style
Case "Normal"
Range(Cells(Target.Row, Target.Column), Cells(Target.Row, Target.Column)).Style = "Accent1"
getData
putData
Case "Accent1"
Range(Cells(Target.Row, Target.Column), Cells(Target.Row, Target.Column)).Style = "Normal"
Range(Cells(Target.Row, Target.Column + 1), Cells(Target.Row, Target.Column + 3)).Value = ""
Case Else
End Select
Else
' No cell of Target in in the range. Get Out.
GoTo ExitSubCorrectly
End If
ExitSubCorrectly:
' go back and turn on changes
' MsgBox Err.Description
Worksheets("Sheet1").Select
Application.EnableEvents = True
End Sub
Sub getData()
Worksheets("Sheet2").Select
Range(Cells(getRow, getCol), Cells(getRow, getCol)).Select
benRel = Range(Cells(getRow, getCol), Cells(getRow, getCol)).Offset(0, 1).Value
rskOpt = Range(Cells(getRow, getCol), Cells(getRow, getCol)).Offset(0, 2).Value
resOpt = Range(Cells(getRow, getCol), Cells(getRow, getCol)).Offset(0, 3).Value
End Sub
Sub putData()
Worksheets("Sheet1").Select
Range(Cells(Target.Row, Target.Column), Cells(Target.Row, Target.Column)).Offset(0, 1).Value = benRel
Range(Cells(Target.Row, Target.Column), Cells(Target.Row, Target.Column)).Offset(0, 2).Value = rskOpt
Range(Cells(Target.Row, Target.Column), Cells(Target.Row, Target.Column)).Offset(0, 3).Value = resOpt
End Sub
it looks to me like you could replace all three routines with
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
On Error GoTo ExitSubCorrectly
'turn off multiple recurring changes
Application.EnableEvents = False
'do not allow range selection
If Target.Cells.Count > 1 Then GoTo ExitSubCorrectly
'only allow selection within our range
Set myRange = Range("B8:B24")
If Not Application.Intersect(Target, myRange) Is Nothing Then
' At least one cell of Target is within the range myRange.
' Carry out some action.
With Cells(Target.Row, Target.Column)
Select Case .Style
Case "Normal"
.Style = "Accent1"
.Offset(0, 1).Resize(, 3).Value = Worksheets("Sheet2").Cells(getRow, getCol).Offset(0, 1).Resize(, 3).Value
Case "Accent1"
.Style = "Normal"
.Offset(0, 1).Resize(, 3).ClearContents
Case Else
End Select
End With
End If
ExitSubCorrectly:
' go back and turn on changes
' MsgBox Err.Description
Application.EnableEvents = True
End Sub

Resources