I am trying to do vlookup through the find function in vba. I have a list of numbers in loan sheet and property sheet and If the number is found in the loan sheet then it copies the entire row and pastes it in another sheet called query. This is the code I have currently but the code just hangs as I have too many cells to find around 100,000. Any guidance in any errors in the code would be really helpful.
Option Explicit
Sub FindCopy_lall()
Dim calc As Long
Dim Cel As Range
Dim LastRow As Long
Dim LastRow2 As Long
Dim rFound As Range
Dim LookRange As Range
Dim CelValue As Variant
' Speed
calc = Application.Calculation
With Application
.Calculation = xlCalculationManual
.ScreenUpdating = False
End With
'Get Last row of Property SheetColumn
LastRow = Worksheets("Property").Cells(Rows.Count, "E").End(xlUp).Row
LastRow2 = Worksheets("Loan").Cells(Rows.Count, "D").End(xlUp).Row
' Set range to look in
Set LookRange = Worksheets("Property").Range("E2:E" & LastRow)
' Loop on each value (cell)
For Each Cel In LookRange
' Get value to find
CelValue = Cel.Value
' Look on IT_Asset
' With Worksheets("Loan")
' Allow not found error
On Error Resume Next
Set rFound = Worksheets("Loan").Range("D2:D" & LastRow2).Find(What:=CelValue, _
LookIn:=xlValues, _
Lookat:=xlWhole, MatchCase:=False)
' Reset
On Error GoTo endo
' Not found, go next
If rFound Is Nothing Then
GoTo nextCel
Else
Worksheets("Loan").Range("rFound:rFound").Select
Selection.Copy
Worksheets("Query").Range("Cel:Cel").Select
ActiveSheet.Paste
End If
'End With
nextCel:
Next Cel
'Reset
endo:
With Application
.Calculation = calc
.ScreenUpdating = True
End With
End Sub
Running Find() many times in a loop can be very slow - I usually create a lookup using a Dictionary: typically thus is much faster and makes the loop easier to code.
Sub FindCopy_lall()
Dim calc As Long
Dim Cel As Range, LookRange As Range
Dim LastRow As Long
Dim LastRow2 As Long
Dim CelValue As Variant
Dim dict As Object
calc = Application.Calculation
With Application
.Calculation = xlCalculationManual
.ScreenUpdating = False
End With
LastRow = Worksheets("Property").Cells(Rows.Count, "E").End(xlUp).Row
LastRow2 = Worksheets("Loan").Cells(Rows.Count, "D").End(xlUp).Row
Set dict = RowMap(Worksheets("Loan").Range("D2:D" & LastRow2))
Set LookRange = Worksheets("Property").Range("E2:E" & LastRow)
For Each Cel In LookRange
CelValue = Cel.Value
If dict.exists(CelValue) Then
'just copy values (5 cols, resize to suit)
Cel.Offset(0, 1).Resize(1, 5).Value = _
dict(CelValue).Offset(0, 1).Resize(1, 5).Value
'...or copy the range
'dict(CelValue).Offset(0, 1).Resize(1, 5).Copy Cel.Offset(0, 1)
End If
Next Cel
With Application
.Calculation = calc
.ScreenUpdating = True
End With
End Sub
'map a range's values to their respective cells
Function RowMap(rng As Range) As Object
Dim rv As Object, c As Range, v
Set rv = CreateObject("scripting.dictionary")
For Each c In rng.Cells
v = c.Value
If Not rv.exists(v) Then
rv.Add v, c
Else
MsgBox "Duplicate value detected!"
Exit For
End If
Next c
Set RowMap = rv
End Function
There are many things that needs to be re-written
A) Variables inside the quotes become a string. For example "rFound:rFound" Also you do not need to specify Worksheets("Loan"). before it. It is understood.
You can simply write it as rFound.Select
B) Avoid the Use of .Select It slows down the code. You might want to see this LINK. For example
Worksheets("Loan").Range("rFound:rFound").Select
Selection.Copy
Worksheets("Query").Range("Cel:Cel").Select
ActiveSheet.Paste
The above can be written as
rFound.Copy Cel
Work with Variables/Objects. Try and ignore the use of On Error Resume Next and unnecessary GO TOs if possible.
Try this (UNTESTED)
Option Explicit
Sub FindCopy_lall()
Dim calc As Long, LrowWsI As Long, LrowWsO As Long
Dim Cel As Range, rFound As Range, LookRange As Range
Dim wsI As Worksheet, wsO As Worksheet
calc = Application.Calculation
With Application
.Calculation = xlCalculationManual
.ScreenUpdating = False
End With
Set wsI = ThisWorkbook.Sheets("Property")
Set wsO = ThisWorkbook.Sheets("Loan")
LrowWsI = wsI.Range("E" & wsI.Rows.Count).End(xlUp).Row
LrowWsO = wsO.Range("D" & wsI.Rows.Count).End(xlUp).Row
Set LookRange = wsI.Range("E2:E" & LrowWsI)
For Each Cel In LookRange
Set rFound = wsO.Range("D2:D" & LrowWsO).Find(What:=Cel.Value, _
LookIn:=xlValues, Lookat:=xlWhole, MatchCase:=False)
If Not rFound Is Nothing Then
'~~> You original code was overwriting the cel
'~~> I am writing next to it. Chnage as applicable
rFound.Copy Cel.Offset(, 1)
End If
Next Cel
With Application
.Calculation = calc
.ScreenUpdating = True
End With
End Sub
Besides the possible bugs the two big performance issues are
doing an Excel .Find.. inside your loop over all your source rows, which as has already been noted, is very slow. And
actually cutting and pasting a lot of rows is also pretty slow. If you only care about the values, then you can use range-array data copies instead which are very fast.
This is how I would do it, which should be very fast:
Option Explicit
Option Compare Text
Sub FindCopy_lall()
Dim calc As Long, CelValue As Variant
Dim LastRow As Long, LastRow2 As Long, r As Long, sr As Long
Dim LookRange As Range, FindRange As Range, rng As Range
Dim LastLoanCell As Range, LastLoanCol As Long
Dim rowVals() As Variant
' Speed
calc = Application.Calculation
Application.Calculation = xlCalculationManual
Application.ScreenUpdating = False
'capture the worksheet objects
Dim wsProp As Worksheet: Set wsProp = Worksheets("Property")
Dim wsLoan As Worksheet: Set wsLoan = Worksheets("Loan")
Dim wsQury As Worksheet: Set wsQury = Worksheets("Query")
'Get Last row of Property SheetColumn
LastRow = wsProp.Cells(Rows.Count, "E").End(xlUp).Row
LastRow2 = wsLoan.Cells(Rows.Count, "D").End(xlUp).Row
Set LastLoanCell = wsLoan.Cells.SpecialCells(xlCellTypeLastCell)
LastLoanCol = LastLoanCell.Column
' Set range to look in; And get it's data
Set LookRange = wsProp.Range("E2:E" & LastRow)
Dim Look() As Variant: ReDim Look(2 To LastRow, 1 To 1)
Look = LookRange
' Index the source values
Dim colIndex As New Collection
For r = 2 To UBound(Look, 1)
' ignore duplicate key errors
On Error Resume Next
colIndex.Add r, CStr(CelValue)
On Error GoTo endo
Next
'Set the range to search; and get its data
Set FindRange = wsLoan.Range("D2:D" & LastRow2)
Dim Find() As Variant: ReDim Find(2 To LastRow2, 1 To 1)
Find = FindRange
' Loop on each value (cell) in the Find range
For r = 2 To UBound(Find, 1)
'Try to find it in the Look index
On Error Resume Next
sr = colIndex(CStr(CelValue))
If Err.Number = 0 Then
'was found in index, so copy the row
On Error GoTo endo
' pull the source row values into an array
Set rng = wsLoan.Range(wsLoan.Cells(r, 1), wsLoan.Cells(r, LastLoanCol))
ReDim rowVals(1 To rng.Rows.Count, 1 To rng.Columns.Count)
rowVals = rng
' push the values out to the target row
Set rng = wsQury.Range(wsQury.Cells(sr, 1), wsQury.Cells(sr, LastLoanCol))
rng = rowVals
End If
On Error GoTo endo
Next r
endo:
'Reset
Application.Calculation = calc
Application.ScreenUpdating = True
End Sub
As others have noted, we cannot tell from your code where the output rows are actually supposed to go on the Query sheet, so I made a guess, but you made need to change that.
Related
I want to combine the functionalities of two codes. My first code is converting a csv file to an excel file and saving it with a different name.
I want to add a functionality of deleting the entire row in a file where column A is #N/A. There may be a small thing to fix it but I am not able to work
it out because I am not good at it.
file = "C:\PR\TEST\Sizetest.csv"
Set fso = CreateObject("Scripting.FileSystemObject")
txt = fso.OpenTextFile(file).ReadAll
fso.OpenTextFile(file, 2).Write Replace(Replace(txt, "¬", vbTab), Chr(34), "")
'Set obj = CreateObject("Scripting.FileSystemObject") 'Calls the File System Object
Const xlDelimited = 1
Const xlNormal = -4143
Dim Excel
Set Excel = CreateObject("Excel.Application")
With Excel
.Workbooks.Open "C:\PR\TEST\Sizetest.csv"
.Sheets(1).Columns("A").TextToColumns .Range("A1"), xlDelimited, , , , True 'semicolon-delimited
.ActiveWorkbook.SaveAs .ActiveWorkbook.Path & "\Size_test1", xlNormal
.Quit
' fso.DeleteFile("C:\PR\TEST\Sizetest.csv") 'Deletes the file throught the DeleteFile function
End With
This is the second code. This should delete entire row whereever there is #N/A in column A. I want the record to be deleted either before the file is
converted to Excel or after it is converted to Excel so it does not matter at what point it should convert it.
I got the following code by searching in the Google but due to not being good at VB script, I am not able to combine them two files. I tried different ways but I am getting one error or another.
Sub macro2()
Dim i As Long, lcol As Long
Application.DisplayAlerts = False
With Worksheets("Sheet1")
lcol = .Range("A1"). End(xLToRight).Column
For i = lcol To 1 Step -1
If.Cells(1, i).Value = "#N/A" Then .Rows(i).Delete
Next i
End With
Application.DisplayAlerts = True
End Sub
Thanks in advance
Updated Code Only to delete #N/A
Sub DeleteErrorRows()
'The path to the workbook in which to search.
'Defining the variables
Dim MyPath, MySheet,MyWB
MyPath = "C:\PR\TEST\Sizetest.xls"
'The name of the workbook in which to search.
MyWB = "SizeGuideLookup_test.xls"
'Use the current sheet as the place to store the data for which to search.
MySheet = ActiveSheet.Name
'If an error occurs, use the error handling routine at the end of this file.
'On Error GoTo ErrorHandler
'Turn off screen updating, and then open the target workbook.
'Application.ScreenUpdating = False
Const strERROR = "#N/A"
Application.ScreenUpdating = False
Dim i, lastRow, rw
Dim rFound
Dim sList
Workbooks.Open MyPath
'Workbooks.Open FileName:=MyPath & MyWB
set wb = Workbooks.Open(objFile.Mypath, ReadOnly:=True, CorruptLoad:=xlExtractData)
wb.Close
Set sList = CreateObject("System.Collections.Sortedlist")
Set rFound = ActiveSheet.Cells.Find(What:=strERROR, After:=Range("A1"), Lookat:=xlPart,LookIn:=xlValues, SearchOrder:=xlByRows, SearchDirection:=xlPrevious, MatchCase:=False)
If rFound Is Nothing Then Exit Sub
lastRow = rFound.Row
For i = 1 To lastRow
Set rFound = Rows(i).Find(What :=strERROR, After:=Rows(i).Cells(1, Columns.Count), Lookat:=xlPart, _
LookIn:=xlValues, SearchOrder:=xlByRows, SearchDirection:=xlNext, MatchCase:=False)
If Not rFound Is Nothing Then
If Not sList.ContainsKey(i) Then
sList.Add i, vbNullString
End If
End If
Next
For i = sList.Count - 1 To 0 Step -1
rw = sList.GetKey(i)
Rows(rw).Delete
Next
DeleteErrorRows
Application.ScreenUpdating = True
'conn.close
End Sub
I am getting error on the following line of code. Error says 'Expected End of Statement )' This code seems ok to me. There might be other errors and I am trying to get this program to work. Set rFound = ActiveSheet.Cells.Find(What:=strERROR, After:=Range("A1"), Lookat:=xlPart,LookIn:=xlValues, SearchOrder:=xlByRows, SearchDirection:=xlPrevious, MatchCase:=False)
Delete all Rows with a #N/A Error from an Excel Worksheet using either VBA or VBScript
Sub RemoveErrorRows(oWorksheet)
Const strERROR = "#N/A"
Const xlValues = -4163
Const xlPart = 2
Const xlByRows = 1
Const xlNext = 1
Dim rFound, lastRow, x
With oWorksheet
Do
Set rFound = .Rows.Find(CStr(strERROR), .UsedRange.Cells(1, .Columns.Count), xlValues, xlPart, xlByRows, xlNext)
If rFound Is Nothing Then
Exit Do
Else
.Rows(rFound.Row).Delete
End If
Loop
End With
End Sub
Below code works great as expected the only downside is its slow because I am using this to search for all the instances of the substring and delete the Entire row if found in any cell of the whole workbook.
Aim is simple just delete the entirerow if the entered string is found in any cell string
Dim wo As Worksheet, ws As Worksheet
Dim I As Long, j As Long, m As Long
Dim toFind As String, testStr As String
Dim pos As Long
Dim lstRow As Long, cutRow As Long
Dim WS_Count As Integer
Dim Cell As Range
Option Compare Text
Option Explicit
Sub SearchDelete()
toFind = InputBox("Enter the substring you want to search for.", "Welcome", "AAAA")
toFind = Trim(toFind)
j = 0
If toFind = "" Then
MsgBox "Empty String Entered.Exiting Sub Now."
Exit Sub
Else
WS_Count = ActiveWorkbook.Worksheets.Count
'Begin the loop.
For I = 1 To WS_Count
Label1:
For Each Cell In Worksheets(I).UsedRange.Cells
If Trim(Cell.Text) <> "" Then
pos = 0
pos = InStr(1, Trim(Cell.Text), toFind, vbTextCompare)
If pos > 0 Then 'match Found'
cutRow = Cell.Row
Worksheets(I).Rows(cutRow).EntireRow.Delete
j = j + 1
GoTo Label1
Else: End If
Else: End If
Next Cell
Next I
End If
MsgBox "Total " & j & " Rows were deleted!"
End Sub
Individual operations are pretty much always slower than bulk operations and the Range.Delete method is no exception. Collecting the matching rows with a Union method and then performing the removal en masse will significantly speed up the operation.
Temporarily suspending certain application environment handlers will also help things along. You do not need Application.ScreenUpdating active while you are removing rows; only after you have completed the operation.
Option Explicit
Option Compare Text
Sub searchDelete()
Dim n As Long, w As Long
Dim toFind As String, addr As String
Dim fnd As Range, rng As Range
toFind = InputBox("Enter the substring you want to search for.", "Welcome", "AAAA")
toFind = Trim(toFind)
If Not CBool(Len(toFind)) Then
MsgBox "Empty String Entered.Exiting Sub Now."
GoTo bm_Safe_Exit
End If
'appTGGL bTGGL:=False 'uncomment this line when you have finsihed debugging
With ActiveWorkbook
For w = 1 To .Worksheets.Count
With .Worksheets(w)
Set fnd = .Cells.Find(what:=toFind, lookat:=xlPart, _
after:=.Cells.SpecialCells(xlCellTypeLastCell))
If Not fnd Is Nothing Then
Set rng = .Rows(fnd.Row)
n = n + 1
addr = fnd.Address
Do
If Intersect(fnd, rng) Is Nothing Then
n = n + 1
Set rng = Union(rng, .Rows(fnd.Row))
End If
Set fnd = .Cells.FindNext(after:=fnd)
Loop Until addr = fnd.Address
Debug.Print rng.Address(0, 0)
rng.Rows.EntireRow.Delete
End If
End With
Next w
End With
Debug.Print "Total " & n & " rows were deleted!"
bm_Safe_Exit:
appTGGL
End Sub
Public Sub appTGGL(Optional bTGGL As Boolean = True)
Application.ScreenUpdating = bTGGL
Application.EnableEvents = bTGGL
Application.DisplayAlerts = bTGGL
Application.Calculation = IIf(bTGGL, xlCalculationAutomatic, xlCalculationManual)
Debug.Print Timer
End Sub
The answer to your question: "How to speed up this code to find and delete rows if a substring is found" is - DON'T repeat the search from the top of the sheet after you found and removed the row!
This sub removes all command buttons and their associated rows that were created programmatically on a sheet. It takes around 20 seconds to remove 60 command buttons and rows. I've stepped through it and can find no problems with it.
Sub ResetForm_Click()
Dim Contr
Dim controlname As String
Dim WS As Worksheet
Set WS = ActiveSheet
For Each Contr In WS.OLEObjects
controlname = Mid(Contr.Name, 1, 2)
If controlname = "CB" Then
Contr.TopLeftCell.Rows.EntireRow.Delete
Contr.Delete
End If
Next
End Sub
Instead of deleting rows one-by-one try something like this (untested):
Sub ResetForm_Click()
Dim Contr
Dim controlname As String
Dim WS As Worksheet, rDel As Range
Set WS = ActiveSheet
For Each Contr In WS.OLEObjects
controlname = Mid(Contr.Name, 1, 2)
If controlname = "CB" Then
If rDel Is Nothing then
Set rDel = Contr.TopLeftCell
Else
Set rDel = Application.Union(rDel, Contr.TopLeftCell)
End If
Contr.Delete
End If
Next
If Not rDel Is Nothing then rDel.EntireRow.Delete
End Sub
Without editing your macro too much, turn off screen updating and autocalculation, see if that helps.
At the beginning of your macro (I usually put it after my declarations), add
Application.ScreenUpdating = False
Application.Calculation = xlCalculationManual
Then at the end (before End Sub), turn them back on
Application.ScreenUpdating = True
Application.Calculation = xlCalculationAutomatic
I've created this code which is copying all values from 'Sheet1' - starting in A2 cell to the first empty row of column 1 in Sheet2.
In case that more cells are needed to be copied, it is running quite long. Is there a possibility to make it run faster?
Thanks
Sub CopyCells()
Dim CopyRow As Long
CopyRow = Sheets("Sheet2").Cells(Rows.Count, 1).End(xlUp).Row 'find last first empty cell in destination sheet
'Sheets("Sheet1").Range("A2").Copy Destination:=Sheets("Sheet2").Range("A" & CopyRow + 1)
Call turn_on_off(False)
For I = 2 To Sheets("Sheet1").Cells(Rows.Count, 1).End(xlUp).Row
Sheets("Sheet1").Range("A" & I).Copy Destination:=Sheets("Sheet2").Range("A" & CopyRow + I - 1)
Next I
Call turn_on_off(True)
End Sub
Public Sub turn_on_off(mode As Boolean)
With Application
.Calculation = IIf(mode = True, xlCalculationAutomatic, xlCalculationManual)
.ScreenUpdating = mode
End With
End Sub
There is no need to use loop:
Sub CopyCells()
Dim CopyRow As Long
Dim lastrow As Long
Dim sh1 As Worksheet, sh2 As Worksheet
Call turn_on_off(False)
Set sh1 = ThisWorkbook.Worksheets("Sheet1")
Set sh2 = ThisWorkbook.Worksheets("Sheet2")
lastrow = sh1.Cells(Rows.Count, 1).End(xlUp).Row
CopyRow = sh2.Cells(Rows.Count, 1).End(xlUp).Row
sh2.Range("A" & CopyRow + 1).Resize(lastrow - 1).Value = _
sh1.Range("A2:A" & lastrow).Value
Call turn_on_off(True)
End Sub
Range.Value=Range.Value is much faster then Copy/Paste, however it copies only values (without formatting). If you need to copy formatting as well, change Range.Value=Range.Value part to:
sh1.Range("A2:A" & lastrow).Copy Destination:=sh2.Range("A" & CopyRow + 1)
I have written a little sub to filter approx. 56.000 items in an Excel List.
It works as expected, but it gets really slower and slower after like 30.000 Iterations. After 100.000 Iterations it's really slow...
The Sub checks each row, if it contains any of the defined words (KeyWords Array). If true, it checks if it is a false positive and afterwards deletes it.
What am I missing here? Why does it get so slow?
Thanks...
Private Sub removeAllOthers()
'
' removes all Rows where Name does not contain
' LTG, Leitung...
'
Application.ScreenUpdating = False
Dim TotalRows As Long
TotalRows = Cells(rows.Count, 4).End(xlUp).row
' Define all words with meaning "Leitung"
KeyWords = Array("LTG", "LEITUNG", "LETG", "LEITG", "MASSE")
' Define all words which are false positives"
BadWords = Array("DUMMY", "BEF", "HALTER", "VORSCHALTGERAET", _
"VORLAUFLEITUNG", "ANLEITUNG", "ABSCHIRMUNG", _
"AUSGLEICHSLEITUNG", "ABDECKUNG", "KAELTEMITTELLEITUNG", _
"LOESCHMITTELLEITUNG", "ROHRLEITUNG", "VERKLEIDUNG", _
"UNTERDRUCK", "ENTLUEFTUNGSLEITUNG", "KRAFTSTOFFLEITUNG", _
"KST", "AUSPUFF", "BREMSLEITUNG", "HYDRAULIKLEITUNG", _
"KUEHLLEITUNG", "LUFTLEITUNG", "DRUCKLEITUNG", "HEIZUNGSLEITUNG", _
"OELLEITUNG", "RUECKLAUFLEITUNG", "HALTESCHIENE", _
"SCHLAUCHLEITUNG", "LUFTMASSE", "KLEBEMASSE", "DICHTUNGSMASSE")
For i = TotalRows To MIN_ROW Step -1
Dim nmbr As Long
nmbr = TotalRows - i
If nmbr Mod 20 = 0 Then
Application.StatusBar = "Progress: " & nmbr & " of " & TotalRows - MIN_ROW & ": " & Format(nmbr / (TotalRows - MIN_ROW), "Percent")
End If
Set C = Range(NAME_COLUMN & i)
Dim Val As Variant
Val = C.Value
Dim found As Boolean
For Each keyw In KeyWords
found = InStr(1, Val, keyw) <> 0
If (found) Then
Exit For
End If
Next
' Check if LTG contains Bad Word
Dim badWord As Boolean
If found Then
'Necessary because SCHALTER contains HALTER
If InStr(1, Val, "SCHALTER") = 0 Then
'Bad Word filter
For Each badw In BadWords
badWord = InStr(1, Val, badw) <> 0
If badWord Then
Exit For
End If
Next
End If
End If
If found = False Or badWord = True Then
C.EntireRow.Delete
End If
Next i
Application.StatusBar = False
Application.ScreenUpdating = True
End Sub
Typically, performing read from / write to operations on ranges in long loops are slow, compared to loops that are performed in memory.
A more performant approach would be to load the range into memory, perform the operations in memory (on array level), clear the contents of the entire range and display the new result (after operations on the array) at once in the sheet (no constant Read / Write but only Read and Write a single time).
Below you find a test with 200 000 rows that illustrates what I aim at, I suggest you check it out.
If it is not a hundred percent what you were looking for, you can finetune it in any way you wish.
I noticed that the screen becomes blank at a certain point; don't do anything, the code is still running but you may be temporarily blocked out of the Excel application.
However you'll notice that it is faster.
Sub Test()
Dim BadWords As Variant
Dim Keywords As Variant
Dim oRange As Range
Dim iRange_Col As Integer
Dim lRange_Row As Long
Dim vArray As Variant
Dim lCnt As Long
Dim lCnt_Final As Long
Dim keyw As Variant
Dim badw As Variant
Dim val As String
Dim found As Boolean
Dim badWord As Boolean
Dim vArray_Final() As Variant
Keywords = Array("LTG", "LEITUNG", "LETG", "LEITG", "MASSE")
BadWords = Array("DUMMY", "BEF", "HALTER", "VORSCHALTGERAET", _
"VORLAUFLEITUNG", "ANLEITUNG", "ABSCHIRMUNG", _
"AUSGLEICHSLEITUNG", "ABDECKUNG", "KAELTEMITTELLEITUNG", _
"LOESCHMITTELLEITUNG", "ROHRLEITUNG", "VERKLEIDUNG", _
"UNTERDRUCK", "ENTLUEFTUNGSLEITUNG", "KRAFTSTOFFLEITUNG", _
"KST", "AUSPUFF", "BREMSLEITUNG", "HYDRAULIKLEITUNG", _
"KUEHLLEITUNG", "LUFTLEITUNG", "DRUCKLEITUNG", "HEIZUNGSLEITUNG", _
"OELLEITUNG", "RUECKLAUFLEITUNG", "HALTESCHIENE", _
"SCHLAUCHLEITUNG", "LUFTMASSE", "KLEBEMASSE", "DICHTUNGSMASSE")
Set oRange = ThisWorkbook.Sheets(1).Range("A1:A200000")
iRange_Col = oRange.Columns.Count
lRange_Row = oRange.Rows.Count
ReDim vArray(1 To lRange_Row, 1 To iRange_Col)
vArray = oRange
For lCnt = 1 To lRange_Row
Application.StatusBar = lCnt
val = vArray(lCnt, 1)
For Each keyw In Keywords
found = InStr(1, val, keyw) <> 0
If (found) Then
Exit For
End If
Next
If found Then
'Necessary because SCHALTER contains HALTER
If InStr(1, val, "SCHALTER") = 0 Then
'Bad Word filter
For Each badw In BadWords
badWord = InStr(1, val, badw) <> 0
If badWord Then
Exit For
End If
Next
End If
End If
If found = False Or badWord = True Then
Else
'Load values into a new array
lCnt_Final = lCnt_Final + 1
ReDim Preserve vArray_Final(1 To lCnt_Final)
vArray_Final(lCnt_Final) = vArray(lCnt, 1)
End If
Next lCnt
oRange.ClearContents
set oRange = nothing
If lCnt_Final <> 0 Then
Set oRange = ThisWorkbook.Sheets(1).Range(Cells(1, 1), Cells(lCnt_Final, 1))
oRange = vArray_Final
End If
End Sub