3

I am working on an excel worksheet with multiple columns and roughly 6000 rows. Sheet1 will contain the main information.(the 6000 rows and columns to R). Sheet2 is my exceptions list I need to use for filtering/deleting these rows.

Right now this is what I am using and it only finds exact matches. I need this to find exceptions from sheet2 even if they are part of another word.

For example: when I run this it will find and delete every row that contains just the word hello. but not hello world or hello foo. I need this to delete the row with hello world and hello foo as well.

I am trying to set this up this way so i can simply add more items to my exceptions list and delete more rows as needed.

Sub CheckA()
Dim LR As Long, i As Long
With Sheets("IR Temp")
    LR = .Range("A" & Rows.Count).End(xlUp).Row
    For i = LR To 1 Step -1
        If IsNumeric(Application.Match(.Range("A" & i).Value, Sheets("Exceptions").Columns("A"), 0)) Then .Rows(i).Delete
    Next i
End With
End Sub

How can I make this less specific? I understand it is working how it is supposed to and is finding the exact match but I need it to find and delete the row if that value is found with any combinations of other characters with it.

  • 1
    I'm not voting to close this question but I have covered this in at least a half-dozen other questions. See [Set Auto Filtering multiple wildcards](http://stackoverflow.com/questions/16602872/set-auto-filtering-multiple-wildcards). That Q also has some links to excluding certain values from wildcard matches. –  Jan 22 '16 at 21:18
  • I see where the Auto Filtering with Multiple wildcards is going I think but this is having me put every exception or filtered item one at a time instead of pulling it from the first column of the second sheet it. I need this to look at that sheet and get the list of items to be filtered out because I will not be the only person updating this exceptions list and it may be updated later by another program. – Christopher Zion Hall Jan 22 '16 at 21:58
  • Anything that is on the worksheet can be read into an array and looped through. The [AutoFilter method](https://msdn.microsoft.com/en-us/library/office/aa221844.aspx) is just more efficient than looping through single deletions (which also may not cover **every** occurrance). –  Jan 22 '16 at 22:05
  • 1
    Holy cow @Jeeped I just read through the answer you linked to and had my mind blown by using a `Scripting.Dictionary`'s keys as `Criteria`. [Whatttttttttttttt](http://www.reactiongifs.com/wp-content/uploads/2013/10/tim-and-eric-mind-blown.gif) so solid – Dan Wagner Jan 22 '16 at 22:17
  • @DanWagner - thank you! There was an evolution of answers building up to that method but I'm happy with what resulted. Tests very fast on large blocks of data. –  Jan 22 '16 at 22:29
  • Hey @Jeeped -- I'm 100% on team "use `Range.Autofilter` instead of `For i = 100000 to 2 Step -1`" with you, the performance is incredible. I even did a short screencast comparing the two in [this answer](http://stackoverflow.com/questions/34889521/for-loop-to-delete-rows/34892113#34892113) – Dan Wagner Jan 22 '16 at 22:36

2 Answers2

3

The MATCH function can accept wildcard matches but you need to reverse the way you are identifying the rows to delete. Simply prefix and suffix the criteria rtem with asterisks (e.g Chr(42) ).

Your code did not remove more than a single occurrence of the criteria value. Probably better to loop it until there are no more matches. Since MATCH returns an error on no-match, it might be better to rely on the COUNTIF function to return a value greter than zero.

Sub CheckA()
    Dim str As String, a As Long, vSTRs As Variant

    With Worksheets("Exceptions")
        vSTRs = .Range(.Cells(1, 1), .Cells(Rows.Count, 1).End(xlUp)).Value2
    End With

    With Sheets("IR Temp")
        For a = LBound(vSTRs, 1) To UBound(vSTRs, 1)
            If CBool(Len(Trim(CStr(vSTRs(a, 1))))) Then
                str = Chr(42) & vSTRs(a, 1) & Chr(42)
                Do While CBool(Application.CountIf(.Columns(1), str))
                    .Rows(Application.Match(str, .Columns(1), 0)).EntireRow.Delete
                Loop
            End If
        Next a
    End With
End Sub

This will be a little more time-consuming than identifing a block or union of non-contiguous rows to delete but it will get the job done. Turn off environment variables like screen updating and calculation to speed things up once it runs to your satisfaction.

  • I am now running into the "Excel VBA Run-time error '13' Type mismatch" I have an idea why and i'm reading more into it. I know didn't mention this before but in Sheets("IR Temp") column A there are also numbers and % : % ? $ _ . ( ) Also the in Worksheets("Exceptions") filter list. – Christopher Zion Hall Jan 22 '16 at 22:52
  • In that case my original suggestion from the Q's comments would be more appropriate. –  Jan 22 '16 at 22:54
1

The below assumes your list of words to search for is in Sheet2 column A and your list to check them in are Sheet1 column A starting row 2. There may be a nicer way than a nested loop, but what we have here is putting your list of words into an array, looping through all the cells we want to see if they contain one of the words and for each of those cells looping through to check if one of the listed words is there.

Public Sub testing()

Dim x As Integer
Dim i As Integer
Dim ws As Worksheet
Dim listws As Worksheet
Dim endList As Integer
Dim endR As Integer
Dim arr() As Variant

Set ws = ThisWorkbook.Worksheets("Sheet1")
endR = ws.Cells(ws.Rows.Count, "A").End(xlUp).Row
Set listws = ThisWorkbook.Worksheets("Sheet2")
endList = listws.Cells(ws.Rows.Count, "A").End(xlUp).Row
arr = listws.Range("A1:A" & endList)

x = 2
While x <= endR
    For i = 1 To UBound(arr, 1)
        If InStr(ThisWorkbook.Worksheets("Sheet1").Cells(x, 1).Value, arr(i, 1)) > 0 Then
            ThisWorkbook.Worksheets("Sheet1").Cells(x, 1).EntireRow.Delete
        End If
    Next i
    x = x + 1
Wend

End Sub
andrewf
  • 375
  • 4
  • 10
  • You are correct, this does work but not as I need. I still need this to use the second sheet as a working list I can add to. I do not want to have to add every item I need to filter out of this list in the VBA since there are a growing number of them that have to be easily updated. Jeeped has pointed me in the direction of using an Array if I am understanding this correctly. Or maybe i'm more confused now then when I started. What I do know for sure is, I have alot more reading to do since I am so new to programming. – Christopher Zion Hall Jan 23 '16 at 12:15
  • This is sorta working for me! And thanks for this one :D Right now the only Problem I am having with it, is that I have to run the macro a few times to get all of the rows deleted. It will miss some of them sometimes. Other than that my exceptions list is working out pretty well and everything is shifting up nicely. I need to work on some modifications to it though. – Christopher Zion Hall Jan 24 '16 at 15:16
  • Now that my list is about a third of it's original size I have figured out that I have items that are (almost) duplicates that i need to work out how to get rid of. For instance sdf_left.top.var.status and sdf_left.top.var.value for me are two seperate rows but I only need one of them. I can't just add .status or .value to my exceptions list because I have other items I do not want filtered with .value or .status on the end. sdf_left.top.var.status ~needs to be removed. sdf_left.top.var.value ~needs to stay sdf_left.top.bit.value ~needs to stay sdf_left.right.var.status ~needs to stay – Christopher Zion Hall Jan 24 '16 at 15:30
  • can't you just put the whole of sdf_left.top.var.status in your delete words list? – andrewf Jan 24 '16 at 23:10
  • That would work if that were the only one to filter and I knew the name of each combinations. in this small data base of 6k lines it is possible. Some of my list are upwards of 15-25k lines. if i added each one it could be hundreds of more exceptions added. I understand if i did this once it would be dont for good. until i got a new database. Part of the problem is, i do not know what all will be in the databases. – Christopher Zion Hall Jan 25 '16 at 21:12