0

I have a For Each Loop that looks for cells that contain a string with a wildcard and if that string is not bold. If those conditions are met then that cell's row is deleted. I believe the For Each Loop is inefficient, and even with only around 200 rows the code takes a few seconds to run. Is there a more efficient way to achieve these results?

Dim Cell As Range
Dim sheetRange As Range
Set sheetRange = ActiveSheet.UsedRange

For Each Cell In sheetRange

Set Cell = sheetRange.Find(What:="Total*", lookat:=xlPart)

If Not Cell Is Nothing Then
    If Cell.Font.Bold = False Then
        Cell.EntireRow.Delete
    End If
End If

Next Cell
5
  • 1
    Why are you looping through every cell? You can use Find/FindNext. Commented Feb 22, 2021 at 15:55
  • 1
    ^^^ Can Total* be in any cell or just one column? If the later then loop just that column. Also use Union to create a unioned range so you only delete once. There are many examples on how to do that on this site. Commented Feb 22, 2021 at 15:57
  • Or use Range.AutoFilter if Total* is just in one column and skip looping. Commented Feb 22, 2021 at 15:58
  • @ScottCraner Total* can be in columns B through D currently, but I would like to future proof the code and look in all cells. Commented Feb 22, 2021 at 16:03
  • Then do the second part of my comment. set a range variable using Union. Then delete that range after the loop. Commented Feb 22, 2021 at 16:08

1 Answer 1

1

Please take a look at the code below and see if you can adapt it to your specific use case. The DeleteTotalRows subroutine uses the built-in .Find method to jump specifically to cells that include the value 'Total'. It passes each of these cells to the MergeDeleteRange subroutine. This sub will build a range to delete, which contains all rows with the Total word and bold font.

Report back if you run into issues.

Option Explicit

Sub DeleteTotalRows()
    Dim fnd As Range
    Dim rngToDelete As Range
    Dim firstFnd As Range
    Dim sht As Worksheet
    
    'Update this
    Set sht = Worksheets("Sheet2")
    
    With sht
        Set fnd = .Cells.Find(what:="Total", lookat:=xlPart)
        
        If fnd Is Nothing Then Exit Sub
        
        Set firstFnd = fnd
        
        Do
            MergeDeleteRange rngToDelete, fnd
            Set fnd = .Cells.Find(what:="Total", lookat:=xlPart, after:=fnd)
            
        Loop While fnd.Address <> firstFnd.Address
        
    End With
    
    If rngToDelete Is Nothing Then Exit Sub
    
    rngToDelete.Delete
    
End Sub


Private Sub MergeDeleteRange(ByRef outputRng As Range, ByRef inputCell As Range)
    'Not deleting if the cell isn't bold
    If Not inputCell.Font.Bold Then Exit Sub
    
    'Create output range if it's still empty
    If outputRng Is Nothing Then Set outputRng = inputCell.EntireRow
    
    'Since you are testing multiple columns, confirm that the
    'row isn't already in the output range
    If Not Intersect(inputCell, outputRng) Is Nothing Then
        Exit Sub
    End If
    
    Set outputRng = Union(outputRng, inputCell.EntireRow)
End Sub
Sign up to request clarification or add additional context in comments.

2 Comments

Seems to work great, thank you. I just needed to change If Not inputCell.Font.Bold Then Exit Sub to If inputCell.Font.Bold Then Exit Sub.
@duberry That was my mistake. I misread and thought you were deleting the bold cells. Glad you were able to get it all sorted out!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.