See if this SentenceCase sub works for you.
Sub SentenceCase(rng As Range)
Dim V As Variant
Dim s As String
Dim Start As Boolean
Dim i As Long
Dim ch As String
Application.ScreenUpdating = False
Application.EnableEvents = False
ActiveSheet.Unprotect
With rng
V = .Value
If IsDate(V) Or IsNumeric(V) Then Exit Sub
s = CStr(V)
Start = True
For i = 1 To Len(s)
ch = Mid$(s, i, 1)
Select Case ch
Case "."
Start = True
Case "?"
Start = True
Case "!"
Start = True
Case "a" To "z"
If Start Then ch = UCase$(ch)
Start = False
Case "A" To "Z"
If Start Then
Start = False
Else
ch = LCase$(ch)
End If
End Select
Mid$(s, i, 1) = ch
Next i
.Value = s
End With
ActiveSheet.Protect
Application.ScreenUpdating = True
Application.EnableEvents = True
End Sub
Another problem you have is that the Worksheet Change sub is too overloaded. It should look like this, which only checks for the changed cell and selects a sub to run against it. Note that every sub it calls should have Protection, Screen Updating, and Events Enabling code.
Private Sub Worksheet_Change(ByVal Target As Range)
Dim myrange As Range
Set myrange = Range("B9:B15,B19:B22,B27:B36,F9:F15,F19:F22,F27:F36,H45,G46")
If Not Intersect(Target, myrange) Is Nothing Then SetProper Target
Select Case Target.Address
Case "$B$38"
SentenceCase Target
Case "$K$47", "$N$3", "$R$3"
CheckDates Target
Case "$N$4", "$R$4", "$R$47"
CheckHours Target
End Select
End Sub