Try and see
Sub FormatSubtotal(Optional ByVal strColumnLetter As String, _
Optional ByVal strKeyWord As String = "Total", _
Optional ByVal shToCheck As Worksheet)
Dim rToSearch As Range
Dim rFound As Range
Dim strFirstAddress As String
' Check the sheet if not the default.
If shToCheck Is Nothing Then Set shToCheck = ActiveSheet
' IF function not used. strColumnLetter is absolutely required above.
If strColumnLetter = vbNullString Then
Set rToSearch = shToCheck.UsedRange
'Use with caution if strKeyWord in multiple columns
Else
Set rToSearch = shToCheck.Columns(strColumnLetter)
End If
' Perform the actual search.
With rToSearch
Set rFound = .Find(What:=strKeyWord, LookIn:=xlValues, _
LookAt:=xlPart, SearchOrder:=xlByRows, _
SearchDirection:=xlNext, MatchCase:=True, _
Matchbyte:=False, SearchFormat:=False)
If Not rFound Is Nothing Then
strFirstAddress = rFound.Offset(1).Address
Do
'ToDo: Make everything uppercase
With rFound.EntireRow
'EntireRow prevents partial shifts when
'strColumnLetter is not "A
.Font.Bold = True
.Insert
.Offset(1, 0).Insert
End With
Set rFound = .FindNext(rFound)
Loop While rFound.Address <> strFirstAddress
End If
End With
' Clean up
Set rFound = Nothing
Set rToSearch = Nothing
Set shToCheck = Nothing
End Sub
Note that if you make strColumnLetter optional and search UsedRange using LookAt:=xlPart, then this sub will insertrows at, for ex. "SubTotal," "Total," and GandTotal," even though they are in different columns.
I think this procedure is half User called and half Code called, without being best for either. If it is to called by Users, then it should only perform specific tasks without need of inputs. This means it needs a definitive name.
Sub FormatArtsDeptQuarterlyBudgetProposal()
Const strColumnLetter As String = "C"
Const strKeyWord As String = "Total"
With ActiveSheet
I think that you do have a good start on a multiuse Call-By-Code procedure, but never use optional parameters if it is called by another procedure. Make the coder, (You) specify what is to happen at every call.
Sub FormatAndSpaceRowsByKeyWord(ByRef wbToCheck As Excel.Workbook, _
ByRef shToCheck As Excel.Worksheet, _
ByRef rRngToCheck As Excel.Range, _
ByVal strKeyWord As String, _
ByVal SpaceAbove As Boolean)
Dim rFound As Range
Dim strFirstAddress As String
On Error GoTo ObjectIssues
'Uber simple test on all Objects at once.
With wbToCheck.shToCheck.rRngToCheck
Err.Clear
' Perform the actual search.
Set rFound = .Find(What:=strKeyWord, LookIn:=xlValues, _
LookAt:=xlWhole, SearchOrder:=xlByRows, _
SearchDirection:=xlNext, MatchCase:=True)
If Not rFound Is Nothing Then
strFirstAddress = rFound.Offset(1).Address
Do
'ToDo: Make everything uppercase
'I would move the Uppercse function completely out of here
'the Replace function is very fast.
'Embolding is so common in these circumstances, that
'I would seriously consider using an Optional (Boolean=True)
'input Parameter for this choice.
With rFound.EntireRow
.Font.Bold = True
If SpaceAbove Then .Insert
.Offset(1, 0).Insert
End With
Set rFound = .FindNext(rFound)
Loop While rFound.Address <> strFirstAddress
End If
End With
GoTo GoodExit
ObjectIssues:
MsgBox "Could not find Sheet " & shToCheck.Name '& " etc
GoTo GoodExit
NextErrorHandler:
GoToGoodExit
GoodExit:
End Sub