I always recommend this when using Worksheet_Change
You do not need the sheet name. It is understood that the code is to be run on current sheet unless you are trying to use another sheet row as a reference as correctly mentioned by brettdj in the comments below.
Whenever you are working with Worksheet_Change event. Always switch Off events if you are writing data to the cell. This is required so that the code doesn't go into a possible endless loop
Whenever you are switching off events, use error handling else if you get an error, the code will not run the next time.
Here is an example
Option Explicit Private Sub Worksheet_Change(ByVal Target As Range) On Error GoTo Whoa Application.EnableEvents = False ' '~~> Rest of the code ' LetsContinue: Application.EnableEvents = True Exit Sub Whoa: MsgBox Err.Description Resume LetsContinue End Sub
So using the above, your code becomes (UNTESTED)
Private Sub Worksheet_Change(ByVal Target As Range) Dim rowCount As Long On Error GoTo Whoa Application.EnableEvents = False With ActiveSheet rowCount = .Cells(.Rows.Count, "A").End(xlUp).Row End With If Not Intersect(Target, Range("M3:M" & rowCount)) Is Nothing Then MsgBox ("Hi") ElseIf Not Intersect(Target, Range("T3:T" & rowCount)) Is Nothing Then MsgBox ("Hi") ElseIf Not Intersect(Target, Range("X3:X" & rowCount)) Is Nothing Then MsgBox ("Hi") ElseIf Not Intersect(Target, Range("AB3:AB" & rowCount)) Is Nothing Then MsgBox ("Hi") ElseIf Not Intersect(Target, Range("AI3:AI" & rowCount)) Is Nothing Then MsgBox ("Hi") End If LetsContinue: Application.EnableEvents = True Exit Sub Whoa: MsgBox Err.Description Resume LetsContinue End Sub
EDIT:
Regarding your 2nd question. As I mentioned in the comment above, you can use a Public variable to check if the worksheet change event is being caused by the workbook open.
Place this code in a module.
Public WasWbOpened As Boolean
Place this code in the workbook code area
Option Explicit Private Sub Workbook_Open() WasWbOpened = True ' '~~> Rest of the code ' WasWbOpened = False End Sub
And change your worksheet change event to
Private Sub Worksheet_Change(ByVal Target As Range) If WasWbOpened = True Then Exit Sub Dim rowCount As Long On Error GoTo Whoa Application.EnableEvents = False With ActiveSheet rowCount = .Cells(.Rows.Count, "A").End(xlUp).Row End With If Not Intersect(Target, Range("M3:M" & rowCount)) Is Nothing Then MsgBox ("Hi") ElseIf Not Intersect(Target, Range("T3:T" & rowCount)) Is Nothing Then MsgBox ("Hi") ElseIf Not Intersect(Target, Range("X3:X" & rowCount)) Is Nothing Then MsgBox ("Hi") ElseIf Not Intersect(Target, Range("AB3:AB" & rowCount)) Is Nothing Then MsgBox ("Hi") ElseIf Not Intersect(Target, Range("AI3:AI" & rowCount)) Is Nothing Then MsgBox ("Hi") End If LetsContinue: Application.EnableEvents = True Exit Sub Whoa: MsgBox Err.Description Resume LetsContinue End Sub
Set rowCount = ws.Cells(Rows.Count, "A").End(xlUp)rowCount is not an object but a variable. UserowCount = ws.Cells(ws.Rows.Count, "A").End(xlUp).RowDim rowCount As Long- there are more rows in a worksheet than anIntegercan hold