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