Delete special rows in every sheet via VBA - vba

I tried to write some code to search for a word and if this word isn't found in the first an second column I delete the row.
This code runs through every Sheet.
Unfortunately this script takes like forever and Excel stops working. It works for one sheet but even if there are just 2 rows, it takes like 10 seconds.
Maybe you can help me to work on the performance, because I never learned VBA and this code is the best I was able to write.
Option Explicit
Sub dontDeleteRowWithInput()
Dim wksSheet As Worksheet
Dim area As Range, i As Integer, j As Integer
Dim rows As Long
Dim Var As String
Dim bool As Boolean
Dim celltxt As String
Var = InputBox("Input", "Input")
Application.ScreenUpdating = False
Application.DisplayAlerts = False
'Loop over every Worksheet in this Workbook
For Each wksSheet In ActiveWorkbook.Worksheets
Set area = wksSheet.UsedRange
rows = area.Rows.Count
'Loop the rows backwards until it reaches row 2 (Row 1 should be ignored)
For j = rows To 2 Step -1
'Search vor the input in Column 1 and 2
For i = 1 To 2 Step 1
'Get the content of the reached cell in string format
celltxt = Cells(j, i).Value
'Compare the saved string with the input
If InStr(celltxt, Var) > 0 Then
'If the input is found in this cell don't delete the row
bool = False
Exit For
End If
'Delete the row if the input wasn't found in its columns
If bool = True Then
Rows(j).Delete
End If
'Reset the bool
bool = True
Next i
Next j
Next wksSheet
Application.ScreenUpdating = True
Application.DisplayAlerts = True
End Sub

Could you try something simpler like:
Dim wksSheet As Worksheet, i As Integer, j As Integer
Dim lastrow As Long
Dim Var As String
Var = InputBox("Input", "Input")
Application.ScreenUpdating = False
Application.DisplayAlerts = False
'Loop over every Worksheet in this Workbook
For Each wksSheet In ThisWorkbook.Worksheets
With wksSheet
lastrow = 0
On Error Resume Next
lastrow = .Cells.Find("*", SearchOrder:=xlByRows, LookIn:=xlValues, SearchDirection:=xlPrevious).Row
If lastrow > 0 And Var <> "" Then
For i = lastrow To 2 Step -1
If InStr(.Cells(i, 1).Text, Var) > 0 Or InStr(.Cells(i, 2).Text, Var) > 0 Then
.rows(i).Delete
End If
Next i
End If
End With
Next
Application.ScreenUpdating = True
Application.DisplayAlerts = True

You can try this, I believe this should work for you. It has not been tested yet.
Sub dontDeleteRowWithInput()
Dim sht As Worksheet
Dim nlast As Long
For Each sht In Sheets
nlast = sht.Cells(sht.Rows.Count, "A").End(xlUp).Row
For n = nlast To 1 Step -1
If sht.Cells(n, 1).Value <> "Input" And sht.Cells(n, 2).Value <> "Input" Then
sht.Rows(n).EntireRow.Delete
End If
Next n
Next sht
End Sub
`

Related

VBA - Delete Every Nth Row On Each Sheet Of Workbook (100k+ values per sheet)

I have a workbook with 10+ sheets, with hundreds of thousands of values in each (125k sheet1, 240k sheet 2, 400k sheet 3, etc.) I am trimming down the sheets by keeping every thousandth or so point in each sheet.
I have been unable to get the code to finish trimming data on the first sheet. The code has run for well over an hour without finishing the first sheet. I've tried with smaller data sets as well (~1000 points in 5 sheets), but the macro only successfully trims points on the first sheet. The other sheets are not modified
Below is the code I'm using to delete an interval of rows; it is the most customizable way to delete rows I could find (which is exactly what i'm looking for: customization/simplicity
lastRow = Application.ActiveSheet.UsedRange.Rows.Count
For i = 2 To lastRow Step 1 'Interval of rows to delete
Range(Rows(i), Rows(i + 997)).Delete Shift:=xlUp
Next i
The code for this specific task is inserted into a modified version of a codes found in this question *credit to those who originally wrote them
Question: Excel VBA Performance - 1 million rows - Delete rows containing a value, in less than 1 min
Here's Helper Functions paul bica used in his code
Public Sub FastWB(Optional ByVal opt As Boolean = True)
With Application
.Calculation = IIf(opt, xlCalculationManual, xlCalculationAutomatic)
.DisplayAlerts = Not opt
.DisplayStatusBar = Not opt
.EnableAnimations = Not opt
.EnableEvents = Not opt
.ScreenUpdating = Not opt
End With
FastWS , opt
End Sub
Public Sub FastWS(Optional ByVal ws As Worksheet = Nothing, _
Optional ByVal opt As Boolean = True)
If ws Is Nothing Then
For Each ws In Application.ActiveWorkbook.Sheets
EnableWS ws, opt
Next
Else
EnableWS ws, opt
End If
End Sub
Private Sub EnableWS(ByVal ws As Worksheet, ByVal opt As Boolean)
With ws
.DisplayPageBreaks = False
.EnableCalculation = Not opt
.EnableFormatConditionsCalculation = Not opt
.EnablePivotTable = Not opt
End With
End Sub
A nifty little code for generating a test set by marko2049:
Sub DevelopTest()
Dim index As Long
FastWB True
ActiveSheet.UsedRange.Clear
For index = 1 To 1000000 '1 million test
ActiveSheet.Cells(index, 1).Value = index
If (index Mod 10) = 0 Then
ActiveSheet.Cells(index, 2).Value = "Test String"
Else
ActiveSheet.Cells(index, 2).Value = "Blah Blah Blah"
End If
Next index
Application.StatusBar = ""
FastWB False
End Sub
After generating a test set and copying it to several sheets, I ran a modified version of the code below
The main body of the code was made by user marko5049
Sub DeleteRowFast()
Dim curWorksheet As Worksheet 'Current worksheet vairable
Dim rangeSelection As Range 'Selected range
Dim startBadVals As Long 'Start of the unwanted values
Dim endBadVals As Long 'End of the unwanted values
Dim strtTime As Double 'Timer variable
Dim lastRow As Long 'Last Row variable
Dim lastColumn As Long 'Last column variable
Dim indexCell As Range 'Index range start
Dim sortRange As Range 'The range which the sort is applied to
Dim currRow As Range 'Current Row index for the for loop
Dim cell As Range 'Current cell for use in the for loop
On Error GoTo Err
Set rangeSelection = Application.InputBox("Select the (N=) range to be checked", "Get Range", Type:=8) 'Get the desired range from the user
Err.Clear
M1 = MsgBox("This is recommended for large files (50,000 or more entries)", vbYesNo, "Enable Fast Workbook?") 'Prompt the user with an option to enable Fast Workbook, roughly 150% performace gains... Recommended for incredibly large files
Select Case M1
Case vbYes
FastWB True 'Enable fast workbook
Case vbNo
FastWB False 'Disable fast workbook
End Select
strtTime = Timer 'Begin the timer
Set curWorksheet = ActiveSheet
lastRow = CLng(rangeSelection.SpecialCells(xlCellTypeLastCell).Row)
lastColumn = curWorksheet.Cells(1, 16384).End(xlToLeft).Column
Set indexCell = curWorksheet.Cells(1, 1)
On Error Resume Next
If rangeSelection.Rows.Count > 1 Then 'Check if there is anything to do
lastVisRow = rangeSelection.Rows.Count
Set sortRange = curWorksheet.Range(indexCell, curWorksheet.Cells(curWorksheet.Rows(lastRow).Row, 16384).End(xlToLeft)) 'Set the sort range
sortRange.Sort Key1:=rangeSelection.Cells(1, 1), Order1:=xlAscending, Header:=xlNo 'Sort by values, lowest to highest
startBadVals = rangeSelection.Find(What:="Test String", LookAt:=xlWhole, MatchCase:=False).Row
endBadVals = rangeSelection.Find(What:="Test String", LookAt:=xlWhole, SearchDirection:=xlPrevious, MatchCase:=False).Row
curWorksheet.Range(curWorksheet.Rows(startBadVals), curWorksheet.Rows(endBadVals)).EntireRow.Delete 'Delete uneeded rows, deleteing in continuous range blocks is quick than seperated or individual deletions.
sortRange.Sort Key1:=indexCell, Order1:=xlAscending, Header:=xlNo 'Sort by index instead of values, lowest to highest
End If
Application.StatusBar = "" 'Reset the status bar
FastWB False 'Disable fast workbook
MsgBox CStr(Round(Timer - strtTime, 2)) & "s" 'Display duration of task
Err:
Exit Sub
End Sub
I've modified the above code as follows
Sub DeleteRowFastMod()
Dim lastRow As Long
Dim i As Long
Dim ws As Worksheet
Dim wb As Workbook
Set wb = Application.ActiveWorkbook
On Error GoTo Err
'Get the desired range from the user
Err.Clear
FastWB True 'Enable fast workbook
strtTime = Timer 'Begin the timer
On Error Resume Next
For Each ws In wb.Worksheets(1) 'Loop through sheets in workbook
ws.Activate
lastRow = Application.ActiveSheet.UsedRange.Rows.Count
If lastRow > 1 Then 'Check if there is anything to do
For i = 2 To lastRow Step 1 'Interval of rows to delete
Range(Rows(i), Rows(i + 997)).Delete Shift:=xlUp
Next i
End If
Next
Application.StatusBar = "" 'Reset the status bar
FastWB False 'Disable fast workbook
MsgBox CStr(Round(Timer - strtTime, 2)) & "s" 'Display duration of task
Err:
Exit Sub
End Sub
I am not sure how to further modify this code to run on each sheet in the workbook in a timely manner.
Thanks in advance for any guidance
You could use the same method as in the link
Excel VBA Performance - 1 million rows - Delete rows containing a value, in less than 1 min
The code bellow (Module 2) sets up test data - 30 million formulas (3 full columns) in 10 Worksheets
The sub in Module 1 loops through all sheets and
hides 1K rows sets
copies visible rows to a new sheet
deletes the initial sheet
Module 1 - Main Sub
Option Explicit
Public Sub TrimLargeData() 'Time: 12.531 sec
Const TRIM_SZ = 1000
Dim t As Double, wb As Workbook, ws As Worksheet
Dim lr As Long, r As Long, newWs As Worksheet, done As Collection
t = Timer: Set wb = ThisWorkbook
FastWB True
Set done = New Collection
For Each ws In wb.Worksheets
done.Add ws
Next
For Each ws In done
lr = ws.UsedRange.Rows.Count
For r = 1 To lr Step TRIM_SZ
If r >= lr - (TRIM_SZ + 1) Then
ws.Range(ws.Cells(r + 1, 1), ws.Cells(lr - 1, 1)).EntireRow.Hidden = True
Exit For
End If
ws.Range(ws.Cells(r + 1, 1), ws.Cells(r + TRIM_SZ - 1, 1)).EntireRow.Hidden = True
Next
Set newWs = Worksheets.Add(After:=Worksheets(Worksheets.Count))
newWs.Name = Left("Trimmed " & ws.Name, 30)
ws.UsedRange.SpecialCells(xlCellTypeVisible).Copy newWs.Cells(1)
ws.Delete
Next
FastWB False: Debug.Print "Time: " & Format(Timer - t, "0.000") & " sec"
End Sub
Module 2 - setup test data subs, and helper procedures
Option Explicit
'generates 30 million formulas (3 full columns) on 10 Worksheets, in about 1 min
Public Sub MakeTestData()
Dim t As Double, ur As Range, ws As Worksheet
t = Timer
FastWB True
FormatCells
MakeWorksheets
With ThisWorkbook
Set ws = .Worksheets(1)
Set ur = ws.Range("A1:C" & ws.Rows.Count)
ur.Formula = "=Address(Row(), Column(), 4)"
.Worksheets.FillAcrossSheets ur
End With
FastWB False
Debug.Print "Time: " & Format(Timer - t, "0.000") & " sec"
End Sub
Private Sub FormatCells()
With ThisWorkbook.Worksheets(1).Cells
.HorizontalAlignment = xlCenter
.VerticalAlignment = xlCenter
.WrapText = False
.IndentLevel = 0
.MergeCells = False
End With
End Sub
Private Sub MakeWorksheets()
Dim ws As Worksheet, i As Long, wsName As Long
With ThisWorkbook
If .Worksheets.Count > 1 Then
For Each ws In .Worksheets
If ws.Index <> 1 Then ws.Delete
Next
End If
For i = 1 To 10
wsName = .Worksheets.Count
.Worksheets.Add(After:=.Worksheets(wsName)).Name = wsName
Next
End With
End Sub
Public Sub FastWB(Optional ByVal opt As Boolean = True)
With Application
.Calculation = IIf(opt, xlCalculationManual, xlCalculationAutomatic)
.DisplayAlerts = Not opt
.DisplayStatusBar = Not opt
.EnableAnimations = Not opt
.EnableEvents = Not opt
.ScreenUpdating = Not opt
End With
FastWS , opt
End Sub
Public Sub FastWS(Optional ByVal ws As Worksheet = Nothing, _
Optional ByVal opt As Boolean = True)
If ws Is Nothing Then
For Each ws In Application.ActiveWorkbook.Sheets
EnableWS ws, opt
Next
Else
EnableWS ws, opt
End If
End Sub
Private Sub EnableWS(ByVal ws As Worksheet, ByVal opt As Boolean)
With ws
.DisplayPageBreaks = False
.EnableCalculation = Not opt
.EnableFormatConditionsCalculation = Not opt
.EnablePivotTable = Not opt
End With
End Sub
I think your biggest performance anchor is that you're deleting so frequently and Excel is having to move around so much data. You might consider clearing contents first and/or using a UNION function to do the delete all in one effort. So here's an example of how both approaches would be written:
Sub UnionExample()
Dim deleteRNG As Range
'You need one start statement that is not a union.
Set deleteRNG = Rows(2)
'Now you can start a loop or use some method to include members in your delete range
Set deleteRNG = Union(deleteRNG, Rows(4))
'when finished creating the delete range, clear contents (it's helped my performance)
deleteRNG.ClearContents
'then do your full delete
deleteRNG.Delete shift:=xlUp
End Sub
Using The SpreadSheetGuru's Timer I removed a total of 1,599,992 from 4 Worksheets in 13.53 seconds.
Sub ProcessWorksheets()
Dim ws As Worksheet
With Application
.ScreenUpdating = False
.Calculation = xlCalculationManual
End With
For Each ws In ThisWorkbook.Worksheets
KeepNthRows ws.UsedRange, 2, 1000
Next
With Application
.ScreenUpdating = True
.Calculation = xlCalculationAutomatic
End With
End Sub
Sub KeepNthRows(Target As Range, FirstRow As Long, NthStep As Long)
Dim data As Variant, results As Variant
Dim x1 As Long, x2 As Long, y As Long
If Target.Rows.Count < 2 Then Exit Sub
FirstRow = FirstRow - 1 'Adjustment needed for using Range.Offset
data = Target.Offset(FirstRow).Value
ReDim results(1 To UBound(data, 1), 1 To UBound(data, 2))
For x1 = FirstRow To UBound(data, 1) Step NthStep
x2 = x2 + 1
For y = 1 To UBound(data, 2)
results(x2, y) = data(x1, y)
Next
Next
Target.Offset(FirstRow).Value = results
End Sub

VBA Delete row if

All i want to do is to optimize my current delete row code.
At this stage this step take to much time.
Dim miesiac2 As Integer '--->current month
miesiac2 = Range("b1").Value
Dim LastRow As Long
LastRow = [A65536].End(xlUp).Row
For i = LastRow To 1 Step -1
If Cells(i, 1) = miesiac2 Then Rows(i & ":" & i).EntireRow.Delete
Next i
So... If column A equals current month then EntireRow.Delete
Any idea?
That's something I have built so far:
Option Explicit
Public Sub TestMe()
Application.ScreenUpdating = False
Dim miesiac2 As Long
Dim LastRow As Long
Dim i As Long
Dim rRange As Range
miesiac2 = Range("b1").Value
LastRow = [A65536].End(xlUp).Row 'xl2003
For i = LastRow To 1 Step -1
If Cells(i, 1) = miesiac2 Then
If rRange Is Nothing Then
Set rRange = Rows(i)
Else
Set rRange = Union(rRange, Rows(i))
End If
End If
Next i
If Not rRange Is Nothing Then rRange.Select
Application.ScreenUpdating = True
End Sub
It uses a Union and it selects the rows instead of deleting them. Its for visibility reasons, but you can fix it.
Furthermore, the 65K rows are only in Excel 2003, in later versions the rows are 1Mln+. Last but not least - do not use integer in Excel, its slow and dangerous.
This is what I could cook up in hurry
Sub delete_on_condition()
Dim wb_export As Workbook
Dim wb_export_sheet As Worksheet
Dim arr_raw_dump As Variant
Dim arr_final
Dim findcell As Range
Set wb_export = ThisWorkbook ' CHANGE IT IF REQURIED
Set wb_export_sheet = wb_export.Sheets(1) 'CHANGE IT IF REQUIRED
Dim ctr As Long
ctr = 0
With wb_export_sheet.Range("A1").CurrentRegion ' OR With wb_export_sheet.USEDRANGE
Do
Set findcell = .Find("SOME TEXT")
If ctr = 0 And findcell Is Nothing Then
MsgBox "No data found"
Exit Sub
End If
wb_export_sheet.Rows(findcell.Row).Delete
Set findcell = .Find("SOMETEXT")
ctr = ctr + 1
Loop While Not findcell Is Nothing
End With
End Sub

How to create a multiple criteria advance filter in VBA?

I'm trying to create an advanced filter for the below table but the code below is just hiding the cells. It's working but my problem with it is if i filter something and then I drag to fill status or any other cells it will override the cells in between for example in filter mode I have 2 rows one is 1st row and the other one is at row 20 if I drag to fill status it will replace the status of all cells in between 1 and 20 and don't know how to work it out, i know this happens because I'm hiding the cells and not actually filtering them.
Any help will be much appreciated.
[Data Table][1]
Private Sub Worksheet_Change(ByVal Target As Range)
Application.ScreenUpdating = False
Application.EnableEvents = False
r1 = Target.Row
c1 = Target.Column
If r1 <> 3 Then GoTo ending:
If ActiveSheet.Cells(1, c1) = "" Then GoTo ending:
Dim LC As Long
With ActiveSheet
LC = .Cells.Find(What:="*", After:=[A1], SearchOrder:=xlByColumns, SearchDirection:=xlPrevious).Column
End With
ActiveSheet.Range("4:10000").Select
Selection.EntireRow.Hidden = False
LR = Cells.Find(What:="*", After:=[A1], SearchOrder:=xlByRows, SearchDirection:=xlPrevious).Row
For r = 5 To LR
For c = 1 To LC
If ActiveSheet.Cells(2, c) = "" Or ActiveSheet.Cells(3, c) = "" Then GoTo nextc:
If ActiveSheet.Cells(2, c) = "exact" And UCase(ActiveSheet.Cells(r, c)) <> UCase(ActiveSheet.Cells(3, c)) Then ActiveSheet.Rows(r).EntireRow.Hidden = True: GoTo nextr:
If Cells(2, c) = "exact" Then GoTo nextc:
j = InStr(1, UCase(ActiveSheet.Cells(r, c)), UCase(ActiveSheet.Cells(3, c)))
If ActiveSheet.Cells(2, c) = "partial" And j = 0 Then ActiveSheet.Rows(r).EntireRow.Hidden = True: GoTo nextr:
nextc:
Next c
nextr:
Next r
ending:
Application.EnableEvents = True
Application.ScreenUpdating = True
End Sub
The below code will be the answer to the question on how to create an advanced search based on multiple criteria on what the user selects in the table.
I will need a little bit of help with how to check if the user selected by mistake an empty cell I will need to make excel ignore filtering the blank cell. Also, I will need to make excel first to check if the yellow cells A3 to T3 has data in and if it has and i press the filter button will filter by the range A3:T3 and ignore the current user selection if there is no data in range A3:T3 will filter by the user selection and in the range A3:T3, if it has data will only filter by data cell that has data in them and ignore empty ones.
Sub advancedMultipleCriteriaFilter()
Dim cellRng As Range, tableObject As Range, subSelection As Range
Dim filterCriteria() As String, filterFields() As Integer
Dim i As Integer
If Selection.Rows.Count > 1 Then
MsgBox "Cannot apply filters to multiple rows within the same column. Please make another selection and try again.", vbInformation, "Selection Error!"
Exit Sub
End If
Application.ScreenUpdating = False
i = 1
ReDim filterCriteria(1 To Selection.Cells.Count) As String
ReDim filterFields(1 To Selection.Cells.Count) As Integer
Set tableObject = Selection.CurrentRegion
For Each subSelection In Selection.Areas
For Each cellRng In subSelection
filterCriteria(i) = cellRng.Text
filterFields(i) = cellRng.Column - tableObject.Cells(1, 1).Column + 1
i = i + 1
Next cellRng
Next subSelection
With tableObject
For i = 1 To UBound(filterCriteria)
.AutoFilter field:=filterFields(i), Criteria1:=filterCriteria(i)
Next i
End With
Set tableObject = Nothing
Application.ScreenUpdating = True
End Sub
Sub resetFilters()
Dim sht As Worksheet
Dim LastRow As Range
Application.ScreenUpdating = False
On Error Resume Next
If ActiveSheet.FilterMode Then
ActiveSheet.ShowAllData
End If
Range("A3:T3").ClearContents
Application.ScreenUpdating = True
Call GetLastRow
End Sub
Private Sub GetLastRow()
'Step 1: Declare Your Variables.
Dim LastRow As Long
'Step 2: Capture the last used row number.
LastRow = Cells(Rows.Count, 8).End(xlUp).Row
'Step 3: Select the next row down
Cells(LastRow, 8).Offset(1, 0).Select
End Sub

Compare two workbook and copy last column if the rest of data matches

Here is a bit of background on what I'm trying to achieve.
I have 2 excel files (Old and New), which contains around 10-15 sheets and each of the sheets contain many rows of data and total number of columns in each sheet is different.
I have reviewed Old file and placed my comments for all the rows in the last column of data in each sheet.
Now whenever I receive a New file, I need to first compare the Sheet name, if matches compare the Row of that sheet to old one if found copy the comment from last column of Old sheet to new one.
In short it's kind of reconciliation sheet.I have tried the following code but not getting how to loop for comparison of Workbook and then rows.
Sub recon()
Dim wb As Workbook
Dim sht As Worksheet
Dim sht2 As Worksheet
Dim rnge As Range
Set wb = Workbooks("OldWB")
For Each sht In wb.Sheets
On Error Resume Next
Set sht2 = ActiveWorkbook.Sheets(sht.Name)
On Error GoTo 0
If Not sht2 Is Nothing Then
For Each rnge In sht.UsedRange
If sht2.Range(rnge.Address).Value = "" And rnge.Value <> "" Then
Copy sht2.Range(rnge.Address).Offset(0,1).Value = rnge.Value
End If
Next rnge
Set sht2 = Nothing
End If
Next sht
Set wb = Nothing
End Sub
Consider following points:
1. This code will give you desired result if sheets in both the workbook are in same order.
2. I am counting number of columns for each row assuming that the number of columns may vary row to row in each sheet. If this is not the case you can assign values to lastColumnCurr and lastColumnOld at the beginning of For Each loop.
Sub recon()
Dim wbOld As Workbook
Dim wsOld As Worksheet, wsCurr As Worksheet
Dim lastRowCurr As Long, lastRowOld As Long, lastColumnCurr As Long, lastColumnOld As Long
Dim i As Long, j As Long
Dim flag As Boolean
Set wbOld = Workbooks("old_test")
For Each wsOld In wbOld.Sheets
lastRowOld = wsOld.Cells(Rows.Count, "A").End(xlUp).Row
On Error Resume Next
Set wsCurr = ActiveWorkbook.Sheets(wsOld.Name)
On Error GoTo 0
If Not wsCurr Is Nothing Then
'get number of rows in current sheet
lastRowCurr = wsCurr.Cells(Rows.Count, "A").End(xlUp).Row
'loop through all the rows
For i = 1 To lastRowCurr
'get number of columns in old and current sheets
lastColumnOld = wsOld.Cells(i, Columns.Count).End(xlToLeft).Column
lastColumnCurr = wsCurr.Cells(i, Columns.Count).End(xlToLeft).Column
'maintain a boolean to check whether all the values in a row are same or not
flag = True
'now loop through all the columns in a row
'here if the row in current sheet is same as the old sheet then there will be one column...
'...less in current sheetin compared to old sheet because of your comment column at the end...
'...hence lastColumnOld - 1
If lastColumnCurr = lastColumnOld - 1 Then
For j = 1 To lastColumnCurr
'now all the cells in a row in both sheets
If wsOld.Cells(i, j).Value <> wsCurr.Cells(i, j).Value Then
'if cell is not same, change boolean to false
flag = False
Exit For
End If
Next j
'if boolean is false then there is difference in rows so do not add comment at the end
If flag = True Then
wsCurr.Cells(i, j).Value = wsOld.Cells(i, j).Value
End If
End If
Next i
Set wsCurr = Nothing
End If
Next wsOld
Set wb = Nothing
End Sub
EDIT# 1
_________________________________________________________________________________
Following code will match each row of active sheet to all rows of the sheet in old workbook.
Sub CompareRows_Mrig()
Dim wbOld As Workbook
Dim wsOld As Worksheet, wsCurr As Worksheet
Dim lastRowCurr As Long, lastRowOld As Long, lastColumnCurr As Long, lastColumnOld As Long
Dim flag As Boolean
Set wbOld = Workbooks("old_test")
For Each wsOld In wbOld.Sheets
lastRowOld = wsOld.Cells(Rows.Count, "A").End(xlUp).Row
On Error Resume Next
Set wsCurr = ActiveWorkbook.Sheets(wsOld.Name)
On Error GoTo 0
If Not wsCurr Is Nothing Then
lastRowCurr = wsCurr.Cells(Rows.Count, "A").End(xlUp).Row
Dim c As Long
Dim rIdx As Long, cIdx As Long
For rIdx = 1 To lastRowCurr
lastColumnCurr = wsCurr.Cells(rIdx, Columns.Count).End(xlToLeft).Column
c = 0
For rIdx2 = 1 To lastRowOld
lastColumnOld = wsOld.Cells(rIdx2, Columns.Count).End(xlToLeft).Column - 1
If lastColumnCurr = lastColumnOld Then
flag = True
For cIdx = 1 To lastColumnCurr
If wsCurr.Cells(rIdx, cIdx).Value <> wsOld.Cells(rIdx2, cIdx).Value Then
flag = False
Exit For
End If
Next
c = c + 1
Debug.Print c
If flag = True Then
wsCurr.Cells(rIdx, cIdx).Value = wsOld.Cells(rIdx2, cIdx).Value
End If
End If
Next
Next
End If
Next wsOld
Set wb = Nothing
End Sub
EDIT# 2
_________________________________________________________________________________
To Speed up the code add following lines in sub:
Sub CompareRows_Mrig()
Application.Calculation = xlCalculationManual
Application.ScreenUpdating = False
'*****************************
'Put Code Here
'*****************************
Application.ScreenUpdating = True
Application.Calculation = xlCalculationAutomatic
End Sub

Efficient way to delete entire row if cell doesn't contain '#' [duplicate]

This question already has answers here:
Delete Row based on Search Key VBA
(3 answers)
Closed 8 years ago.
I'm creating a fast sub to do a validity check for emails. I want to delete entire rows of contact data that do not contain a '#' in the 'E' Column. I used the below macro, but it operates too slowly because Excel moves all the rows after deleting.
I've tried another technique like this: set rng = union(rng,c.EntireRow), and afterwards deleting the entire range, but I couldn't prevent error messages.
I've also experimented with just adding each row to a selection, and after everything was selected (as in ctrl+select), subsequently deleting it, but I could not find the appropriate syntax for that.
Any ideas?
Sub Deleteit()
Application.ScreenUpdating = False
Dim pos As Integer
Dim c As Range
For Each c In Range("E:E")
pos = InStr(c.Value, "#")
If pos = 0 Then
c.EntireRow.Delete
End If
Next
Application.ScreenUpdating = True
End Sub
You don't need a loop to do this. An autofilter is much more efficient. (similar to cursor vs. where clause in SQL)
Autofilter all rows that don't contain "#" and then delete them like this:
Sub KeepOnlyAtSymbolRows()
Dim ws As Worksheet
Dim rng As Range
Dim lastRow As Long
Set ws = ActiveWorkbook.Sheets("Sheet1")
lastRow = ws.Range("E" & ws.Rows.Count).End(xlUp).Row
Set rng = ws.Range("E1:E" & lastRow)
' filter and delete all but header row
With rng
.AutoFilter Field:=1, Criteria1:="<>*#*"
.Offset(1, 0).SpecialCells(xlCellTypeVisible).EntireRow.Delete
End With
' turn off the filters
ws.AutoFilterMode = False
End Sub
NOTES:
.Offset(1,0) prevents us from deleting the title row
.SpecialCells(xlCellTypeVisible) specifies the rows that remain after the autofilter has been applied
.EntireRow.Delete deletes all visible rows except for the title row
Step through the code and you can see what each line does. Use F8 in the VBA Editor.
Have you tried a simple auto filter using "#" as the criteria then use
specialcells(xlcelltypevisible).entirerow.delete
note: there are asterisks before and after the # but I don't know how to stop them being parsed out!
Using an example provided by user shahkalpesh, I created the following macro successfully. I'm still curious to learn other techniques (like the one referenced by Fnostro in which you clear content, sort, and then delete). I'm new to VBA so any examples would be very helpful.
Sub Delete_It()
Dim Firstrow As Long
Dim Lastrow As Long
Dim Lrow As Long
Dim CalcMode As Long
Dim ViewMode As Long
With Application
CalcMode = .Calculation
.Calculation = xlCalculationManual
.ScreenUpdating = False
End With
With ActiveSheet
.Select
ViewMode = ActiveWindow.View
ActiveWindow.View = xlNormalView
.DisplayPageBreaks = False
'Firstrow = .UsedRange.Cells(1).Row
Firstrow = 2
Lastrow = .Cells(.Rows.Count, "E").End(xlUp).Row
For Lrow = Lastrow To Firstrow Step -1
With .Cells(Lrow, "E")
If Not IsError(.Value) Then
If InStr(.Value, "#") = 0 Then .EntireRow.Delete
End If
End With
Next Lrow
End With
ActiveWindow.View = ViewMode
With Application
.ScreenUpdating = True
.Calculation = CalcMode
End With
End Sub
When you are working with many rows and many conditions, you better off using this method of row deletion
Option Explicit
Sub DeleteEmptyRows()
Application.ScreenUpdating = False
Dim ws As Worksheet
Dim i&, lr&, rowsToDelete$, lookFor$
'*!!!* set the condition for row deletion
lookFor = "#"
Set ws = ThisWorkbook.Sheets("Sheet1")
lr = ws.Range("E" & Rows.Count).End(xlUp).Row
ReDim arr(0)
For i = 1 To lr
If StrComp(CStr(ws.Range("E" & i).Text), lookFor, vbTextCompare) = 0 then
' nothing
Else
ReDim Preserve arr(UBound(arr) + 1)
arr(UBound(arr) - 1) = i
End If
Next i
If UBound(arr) > 0 Then
ReDim Preserve arr(UBound(arr) - 1)
For i = LBound(arr) To UBound(arr)
rowsToDelete = rowsToDelete & arr(i) & ":" & arr(i) & ","
Next i
ws.Range(Left(rowsToDelete, Len(rowsToDelete) - 1)).Delete Shift:=xlUp
Else
Application.ScreenUpdating = True
MsgBox "No more rows contain: " & lookFor & "or" & lookFor2 & ", therefore exiting"
Exit Sub
End If
If Not Application.ScreenUpdating Then Application.ScreenUpdating = True
Set ws = Nothing
End Sub
Instead of looping and referencing each cell 1 by 1, grab everything and put it into a variant array; Then loop the variant array.
Starter:
Sub Sample()
' Look in Column D, starting at row 2
DeleteRowsWithValue "#", 4, 2
End Sub
The Real worker:
Sub DeleteRowsWithValue(Value As String, Column As Long, StartingRow As Long, Optional Sheet)
Dim i As Long, LastRow As Long
Dim vData() As Variant
Dim DeleteAddress As String
' Sheet is a Variant, so we test if it was passed or not.
If IsMissing(Sheet) Then Set Sheet = ActiveSheet
' Get the last row
LastRow = Sheet.Cells(Sheet.Rows.Count, Column).End(xlUp).Row
' Make sure that there is work to be done
If LastRow < StartingRow Then Exit Sub
' The Key to speeding up the function is only reading the cells once
' and dumping the values to a variant array, vData
vData = Sheet.Cells(StartingRow, Column) _
.Resize(LastRow - StartingRow + 1, 1).Value
' vData will look like vData(1 to nRows, 1 to 1)
For i = LBound(vData) To UBound(vData)
' Find the value inside of the cell
If InStr(vData(i, 1), Value) > 0 Then
' Adding the StartingRow so that everything lines up properly
DeleteAddress = DeleteAddress & ",A" & (StartingRow + i - 1)
End If
Next
If DeleteAddress <> vbNullString Then
' remove the first ","
DeleteAddress = Mid(DeleteAddress, 2)
' Delete all the Rows
Sheet.Range(DeleteAddress).EntireRow.Delete
End If
End Sub