The below code is not deleting the rows as expected. Can someone tell me what is wrong with it?
With Worksheets("Alerts Ack By Cops")
For rw = .Cells(.Rows.Count, "A").End(xlUp).Row To 2 Step -1
Select Case UCase(.Cells(rw, "A").Value2)
Case "Punna,", "Juleas,"
.Rows(rw).EntireRow.Delete
i = i - 1
End Select
Next rw
End With
When you are looking for text with capital letter using UCase then you need to match with upper case values.
Change
Case "Punna,", "Juleas,"
to
Case "PUNNA,", "JULEAS,"
Also since you want to match the cell which starts with those words, you can use LIKE as shown below
With Worksheets("Alerts Ack By Cops")
For rw = .Cells(.Rows.Count, "A").End(xlUp).Row To 2 Step -1
If UCase(.Cells(rw, "A").Value2) Like "PUNNA,*" Or _
UCase(.Cells(rw, "A").Value2) Like "JULEAS,*" Then
.Rows(rw).EntireRow.Delete
End If
Next rw
End With
Also, using autofilter would be faster. You may want to see Delete row based on partial text. Here the cirteria becomes "=" & strSearch & "*" instead of "=*" & strSearch & "*"
If you still want to delete the rows using a loop then you may want to see Union way of doing it in Excel VBA - Delete empty rows which will increase the speed drastically over a large number of rows.
Delete Rows Using AutoFilter
The first solution illustrates the use of two criteria.
The second solution illustrates how to do the same with an array. Unfortunately AutoFilter can have only two criteria containing wild characters. If you add more, nothing will be filtered.
The third solution illustrates a workaround which allows more than two criteria containing wild characters.
The Code
Option Explicit
Sub deleteTwoCriteria()
Application.ScreenUpdating = False
With Worksheets("Alerts Ack By Cops")
.AutoFilterMode = False
With .Range("A1", .Cells(.Rows.Count, "A").End(xlUp))
.AutoFilter _
Field:=1, _
Criteria1:="Punna,*", _
Operator:=xlOr, _
Criteria2:="Juleas,*"
With .Resize(.Rows.Count - 1).Offset(1)
On Error Resume Next
.SpecialCells(xlCellTypeVisible).EntireRow.Delete
On Error GoTo 0
End With
End With
.AutoFilterMode = False
End With
Application.ScreenUpdating = True
End Sub
Sub deleteArray()
Application.ScreenUpdating = False
With Worksheets("Alerts Ack By Cops")
.AutoFilterMode = False
With .Range("A1", .Cells(.Rows.Count, "A").End(xlUp))
.AutoFilter _
Field:=1, _
Criteria1:=Array("Punna,*", "Juleas,*"), _
Operator:=xlFilterValues
With .Resize(.Rows.Count - 1).Offset(1)
On Error Resume Next
.SpecialCells(xlCellTypeVisible).EntireRow.Delete
On Error GoTo 0
End With
End With
.AutoFilterMode = False
End With
Application.ScreenUpdating = True
End Sub
Sub deleteList()
Const CriteriaList As String = "Punna,*|Juleas,*|R2*"
Dim Criteria() As String: Criteria = Split(CriteriaList, "|")
Application.ScreenUpdating = False
With Worksheets("Alerts Ack By Cops")
.AutoFilterMode = False
With .Range("A1", .Cells(.Rows.Count, "A").End(xlUp))
If .Cells.Count > 1 Then
Dim Data As Variant: Data = .Value
Dim dict As Object
Set dict = CreateObject("Scripting.Dictionary")
dict.CompareMode = vbTextCompare
Dim i As Long
Dim n As Long
For i = 2 To UBound(Data, 1)
For n = 0 To UBound(Criteria)
If LCase(Data(i, 1)) Like LCase(Criteria(n)) Then
dict(Data(i, 1)) = Empty
Exit For
End If
Next n
Next i
If dict.Count > 0 Then
.AutoFilter _
Field:=1, _
Criteria1:=dict.Keys, _
Operator:=xlFilterValues
With .Resize(.Rows.Count - 1).Offset(1)
.SpecialCells(xlCellTypeVisible).EntireRow.Delete
End With
.Worksheet.AutoFilterMode = False
End If
End If
End With
End With
Application.ScreenUpdating = True
End Sub
Related
Sub Macro()
Dim i As Long
For i = Cells(Rows.Count, 14).End(xlUp).Row To 2 Step -1
If Cells(i, 14).Value2 = "APPLE" Then
Rows(i).Delete
End If
Next i
Dim f As Long
For f = Cells(Rows.Count, 14).End(xlUp).Row To 2 Step -1
If Cells(f, 14).Value2 = "NAME" Then
Rows(f).Delete
End If
Next f
End Sub
I have the above mentioned code to delete all the rows that have apple and name on them, If possible I would like excel to execute the code in one or two lines. Your help would be greatly appreciated!
Dim i As Long
For i = Cells(Rows.Count, 14).End(xlUp).Row To 2 Step -1
IF Cells(i, 14).Value2 = "APPLE" OR Cells(i, 14).Value2 = "NAME" THEN Rows(i).Delete
Next i
The fast way to delete rows is using AutoFilter:
Sub FastDelete()
Dim rng As Range, rngVisible As Range
'//Remove filter if any
ActiveSheet.AutoFilterMode = False
'// Get range of only one column (N)
Set rng = Range(Cells(1, 14), Cells(Rows.Count, 14).End(xlUp))
'// Field:=1 because filter has only one field
rng.AutoFilter Field:=1, Criteria1:=Array("APPLE", "NAME"), Operator:=xlFilterValues
'// Have error handling in case if no data is found
On Error Resume Next
With rng
'// Use Offset and Resize to exclude header
Set rngVisible = .Offset(1).Resize(.Rows.Count - 1).SpecialCells(xlCellTypeVisible)
End With
'// If rows were found (i.e. there's no error), delete them
If Err = 0 Then rngVisible.EntireRow.Delete
On Error GoTo 0
'// Remove filter
ActiveSheet.AutoFilterMode = False
End Sub
I have written a simple code to delete the lines of my Excel worksheet where the value is not numerical and where there is no value. But, weirdly enough, the loop executes only once when I run the program.
How can I solve this so that my program deletes all at once the lines that meet my two conditions?
Sub foo()
Dim lRow As Integer
Dim sht As Worksheet
Set sht = ActiveWorkbook.ActiveSheet
lRow = sht.Range("A" & Rows.Count).End(xlUp).Row
For Each c In Range(sht.Cells(2, 1), sht.Cells(lRow, 1))
If (Not IsNumeric(c.Value) Or c.Value = "") Then c.EntireRow.Delete
Next
End Sub
This uses AutoFilter to remove targeted rows in 2 steps:
Criteria1:="=*" shows non-empty strings, Criteria2:="=" shows empty values
Option Explicit
Public Sub foo()
Application.ScreenUpdating = False
With ActiveWorkbook.ActiveSheet.UsedRange
'Step 1 - Remove all strings and empty values:
.AutoFilter field:=1, Criteria1:="=*", Operator:=xlOr, Criteria2:="="
.Offset(1).Resize(.Rows.Count - 1).EntireRow.Delete 'Excludes the header row
'Step 2 - Remove all numbers that are not 6 digits in length:
.AutoFilter field:=1, Criteria1:="<100000", Operator:=xlOr, Criteria2:=">999999"
.Offset(1).Resize(.Rows.Count - 1).EntireRow.Delete 'Excludes the header row
.AutoFilter 'Removes filter
End With
Application.ScreenUpdating = True
End Sub
Edit:
The above version will exclude the header row, which becomes the AutoFilter row (with the arrow)
If there is no header row there are more checks to be done.
For example with this data:
100,000
100,001
100,003
The first visible cell (not included in the filter) will be 100,000 which shouldn't be deleted
If the data is:
Abc
100,000
100,001
100,003
The first visible cell (not included in the filter) will be Abc which should be deleted
So version 2 (bellow) addresses this issue:
Option Explicit
Public Sub foo()
Dim rowsToDelete As Range
Application.ScreenUpdating = False
With ActiveWorkbook.ActiveSheet.UsedRange
'Step 1 - Remove all strings and empty values:
.AutoFilter Field:=1, Criteria1:="=*", Operator:=xlOr, Criteria2:="="
Set rowsToDelete = CheckFirstCell(.Columns(1))
If Not rowsToDelete Is Nothing Then rowsToDelete.EntireRow.Delete
'Step 2 - Remove all numbers that are not 6 digits in length:
.AutoFilter Field:=1, Criteria1:="<100000", Operator:=xlOr, Criteria2:=">999999"
Set rowsToDelete = CheckFirstCell(.Columns(1))
If Not rowsToDelete Is Nothing Then rowsToDelete.EntireRow.Delete
.AutoFilter 'Removes filter
End With
Application.ScreenUpdating = True
End Sub
Private Function CheckFirstCell(ByRef rng As Range) As Range 'It can return Nothing
If Not rng Is Nothing Then
Dim tmp As Variant
With rng
.SpecialCells(xlVisible).Select
tmp = Selection(1).Value2
If Not IsNumeric(tmp) Or (tmp < 100000 Or tmp > 999999) Or Len(tmp) = 0 Then
Set CheckFirstCell = .EntireRow
End If
If Selection.Count > 1 Then
If CheckFirstCell Is Nothing Then
Set CheckFirstCell = .Offset(1).Resize(.Rows.Count - 1).EntireRow
Else
Set CheckFirstCell = .EntireRow
End If
End If
.Cells(1).Select
End With
End If
End Function
I have this code. It loops through a list for the filtering criteria, then if no data to select it shows all data again and loops to the next criteria. If it shows data it end(slDown) and selects all the data showing, copies it and pastes it into another worksheet.
The cleanup script cleans any blank rows and columns and then returns to the original data sheet and deletes the data selected for the copy paste.
The problem is when there is just one row. It moves to the row with data, but when I End(xlDown), it shoots all the way to the bottom and the paste then causes the macro to freeze up.
I nested another if statement to capture if there is only one line of data visible, but I cannot get it to function correctly. Any Suggestions on the nested if statement?
Dim criteria As String
Dim F As Range
Set Rng = Sheets("Reference").Range("W2:W36")
For Each F In Rng
criteria = F
ActiveSheet.Range("$AV$1").AutoFilter Field:=48, Criteria1:="=*BULK SUBSERVIENT*", Operator:=xlAnd
ActiveSheet.Range("$K$1").AutoFilter Field:=11, Criteria1:=criteria
Range("A2:CM" & ActiveSheet.UsedRange.Rows.Count + 1) _
.Cells.SpecialCells(xlCellTypeVisible).Rows(1).Select
If ActiveCell.Value = vbNullString Then
ActiveSheet.ShowAllData
Else
If (ActiveSheet.UsedRange.SpecialCells(xlCellTypeLastCell)) = 2 Then
'Range(Selection).Select
Selection.Copy
Sheets("Bulk Subservient").Select
ActiveSheet.Range("A" & Rows.Count).End(xlUp).Offset(1).Select
ActiveSheet.Paste
Call cleanup
Else
Range(Selection, Selection.End(xlDown)).Select
Selection.Copy
Sheets("Bulk Subservient").Select
ActiveSheet.Range("A" & Rows.Count).End(xlUp).Offset(1).Select
ActiveSheet.Paste
Call cleanup
End If
End If
Next F
I figured it out.... Here is what I did. Thanks all!
I used this If ActiveSheet.UsedRange.SpecialCells(xlCellTypeVisible).Areas.Count <= 2
instead of this (ActiveSheet.UsedRange.SpecialCells(xlCellTypeLastCell)) = 2
Dim criteria As String
Dim F As Range
Set Rng = Sheets("Reference").Range("W2:W36")
For Each F In Rng
criteria = F
ActiveSheet.Range("$AV$1").AutoFilter Field:=48, Criteria1:="=*BULK SUBSERVIENT*", Operator:=xlAnd
ActiveSheet.Range("$K$1").AutoFilter Field:=11, Criteria1:=criteria
Range("A2:CM" & ActiveSheet.UsedRange.Rows.Count + 1) _
.Cells.SpecialCells(xlCellTypeVisible).Rows(1).Select
If ActiveCell.Value = vbNullString Then
ActiveSheet.ShowAllData
Else
If ActiveSheet.UsedRange.SpecialCells(xlCellTypeVisible).Areas.Count <= 2 Then
'Range(Selection).Select
Selection.Copy
Sheets("Bulk Subservient").Select
ActiveSheet.Range("A" & Rows.Count).End(xlUp).Offset(1).Select
ActiveSheet.Paste
Call cleanup
Else
Range(Selection, Selection.End(xlDown)).Select
Selection.Copy
Sheets("Bulk Subservient").Select
ActiveSheet.Range("A" & Rows.Count).End(xlUp).Offset(1).Select
ActiveSheet.Paste
Call cleanup
End If
End If
Next F
I think your code could be much cleaner than this. I prefer to use an auxiliar funcion to make this filter. Something like this:
Function MyFilter(criteria as string) as Range
Set tableRange = ActiveSheet.UsedRange
' Filter
With tableRange
Call .AutoFilter(48, "*BULK SUBSERVIENT*")
Call .AutoFilter(11, criteria)
End With
On Error Resume Next
'This...
Set selectedRange = tableRange.SpecialCells(xlCellTypeVisible)
'...Or (how to remover title).
Set selectedRange = Intersect(tableRange.SpecialCells(xlCellTypeVisible), .[2:1000000])
On Error GoTo 0
With tableRange
Call .AutoFilter(11)
Call .AutoFilter(48)
End With
'Empty Criteria
If WorksheetFunction.CountA(selectedRange) < 2 Then
Exit Sub
End If
Set MyFilter = selectedRange
End Sub
Here is your original code rewritten using the Range.CurrentRegion property to define the range of cells to be filtered.
Dim criteria As String
Dim F As Range, rng As Range
With Worksheets("Reference")
Set rng = .Range(.Cells(2, 23), .Cells(Rows.Count, 23).End(xlUp))
End With
With ActiveSheet '<~~ set this to worksheets("Sheet1") as appropriate
If .AutoFilterMode Then .AutoFilterMode = False
With .Cells(1, 1).CurrentRegion
For Each F In rng
criteria = F
.AutoFilter Field:=48, Criteria1:="*BULK SUBSERVIENT*"
.AutoFilter Field:=11, Criteria1:=criteria
With .Resize(.Rows.Count - 1, .Columns.Count).Offset(1, 0)
If CBool(Application.Subtotal(103, .Cells)) Then
.Copy Destination:=Sheets("Bulk Subservient").Cells(Rows.Count, 1).End(xlUp).Offset(1)
End If
End With
Next F
End With
If .AutoFilterMode Then .AutoFilterMode = False
End With
Here is the same thing that collects all of the criteria terms from the Reference worksheet into a variant array and uses that to filter for all terms at once.
Dim rng As Range
Dim vCRITERIA As Variant, v As Long
With Worksheets("Reference")
ReDim vCRITERIA(1 To 1) '<~~for alternate method
For Each rng In .Range(.Cells(2, 23), .Cells(Rows.Count, 23).End(xlUp))
vCRITERIA(UBound(vCRITERIA)) = rng.Value2
ReDim Preserve vCRITERIA(UBound(vCRITERIA) + 1)
Next rng
ReDim Preserve vCRITERIA(UBound(vCRITERIA) - 1)
End With
With ActiveSheet '<~~ set this to worksheets("Sheet1") as appropriate
If .AutoFilterMode Then .AutoFilterMode = False
With .Cells(1, 1).CurrentRegion
.AutoFilter Field:=48, Criteria1:="*BULK SUBSERVIENT*"
.AutoFilter Field:=11, Criteria1:=(vCRITERIA), Operator:=xlFilterValues
With .Resize(.Rows.Count - 1, .Columns.Count).Offset(1, 0)
If CBool(Application.Subtotal(103, .Cells)) Then
.Copy Destination:=Sheets("Bulk Subservient").Cells(Rows.Count, 1).End(xlUp).Offset(1)
End If
End With
End With
If .AutoFilterMode Then .AutoFilterMode = False
End With
The latter is likely a few milli-seconds faster than the first.
The worksheet's SUBTOTAL function never includes filtered or hidden rows so asking for a count will determine if there is anything to copy. Resizing and offsetting moves to the filtered range.
You will need to reincorporate the Cleanup subroutine.
I would like to do the following using Excel VBA:
1) look for a certain word_1 within a column;
2) if word_1 was found in step (1), go one column to the right and look for another word which is called word_2. If word_2 was found as well, delete the entire row.
If on the other hand, word_2 was not found, the row does not have to be deleted.
The general idea is to search for multiple words in one column and if they are found, also double-check (for safety) if certain affiliated words are in column 2. Only then the entire rows should be deleted.
I made the following little example for testing:
Col1 Col2
xxx xxx
xxx xxx
xxx xxx
findme acg
xxx xxx
findme xxx
In this example I am searching for the word "findme" in column 1 and for the associated word "acg" in column 2. As you can see, row 4 would have to be deleted because both words occur in one row, as opposed to e.g. row 6, where this is not the case.
My final code:
Sub xxx()
Dim aCell As Range, bCell As Range, aSave As String
Dim fndOne As String, fndTwo As String
fndOne = "findme"
fndTwo = "acg"
Dim ws As Worksheet: Set ws = ActiveWorkbook.ActiveSheet
Application.DisplayAlerts = False
Application.ScreenUpdating = False
With ws
Set aCell = .Columns(1).Find(What:=fndOne, LookIn:=xlValues, _
lookat:=xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext, _
MatchCase:=False, SearchFormat:=False)
If Not aCell Is Nothing Then
aSave = aCell.Address
Do
If LCase(.Cells(aCell.row, 2).Value) Like Chr(42) & fndTwo & Chr(42) Then
If bCell Is Nothing Then
Set bCell = .Range("A" & aCell.row)
Else
Set bCell = Union(bCell, .Range("A" & aCell.row))
End If
End If
Set aCell = .Columns(1).FindNext(After:=aCell)
Loop Until aCell.Address = aSave
End If
Set aCell = Nothing
If Not bCell Is Nothing Then bCell.EntireRow.Delete
End With
Application.DisplayAlerts = True
Application.ScreenUpdating = True
End Sub
If you used the Range.Find method and Range.FindNext method, deleting as you go and checking for matching records after each deletion, you should be able to loop through the possibilities quickly.
'delete rows as they are found
Sub delTwofers()
Dim rw As Long, n As Long, cnt As Long, rng As Range
Dim v As Long, sALLTERMs As String, vPAIRs As Variant, vTERMs As Variant
On Error GoTo bm_SafeExit
Application.ScreenUpdating = False
Application.EnableEvents = False
Application.Calculation = xlCalculationManual
Debug.Print Timer
sALLTERMs = "aa;bb|cc;dd|ee;ff"
With Worksheets("Sheet1") 'set this worksheet reference properly!
vPAIRs = Split(LCase(sALLTERMs), Chr(124))
For v = LBound(vPAIRs) To UBound(vPAIRs)
vTERMs = Split(vPAIRs(v), Chr(59))
cnt = Application.CountIfs(.Columns(1), Chr(42) & vTERMs(0) & Chr(42), .Columns(2), Chr(42) & vTERMs(1) & Chr(42))
rw = 1
For n = 1 To cnt
rw = .Columns(1).Find(what:=vTERMs(0), lookat:=xlPart, _
after:=.Columns(1).Cells(rw + (rw <> 1)), MatchCase:=False).Row
Do While True
If LCase(.Cells(rw, 2).Value2) Like Chr(42) & vTERMs(1) & Chr(42) Then
.Rows(rw).Delete
Exit Do
Else
rw = .Columns(1).FindNext(after:=.Cells(rw, 1)).Row
End If
Loop
Next n
Next v
End With
Debug.Print Timer
bm_SafeExit:
Application.Calculation = xlCalculationAutomatic
Application.ScreenUpdating = True
Application.EnableEvents = True
End Sub
'collect rows with Union, delete them all at once
Sub delTwofers2()
Dim rw As Long, n As Long, cnt As Long, rng As Range
Dim v As Long, sALLTERMs As String, vPAIRs As Variant, vTERMs As Variant
On Error GoTo bm_SafeExit
Application.ScreenUpdating = False
Application.EnableEvents = False
Application.Calculation = xlCalculationManual
Debug.Print Timer
sALLTERMs = "aa;bb|cc;dd|ee;ff"
With Worksheets("Sheet1") 'set this worksheet reference properly!
vPAIRs = Split(LCase(sALLTERMs), Chr(124))
For v = LBound(vPAIRs) To UBound(vPAIRs)
vTERMs = Split(vPAIRs(v), Chr(59))
cnt = Application.CountIfs(.Columns(1), Chr(42) & vTERMs(0) & Chr(42), .Columns(2), Chr(42) & vTERMs(1) & Chr(42))
rw = 1
For n = 1 To cnt
rw = .Columns(1).Find(what:=vTERMs(0), lookat:=xlPart, _
after:=.Columns(1).Cells(rw), MatchCase:=False).Row
Do While True
If LCase(.Cells(rw, 2).Value2) Like Chr(42) & vTERMs(1) & Chr(42) Then
If rng Is Nothing Then
Set rng = .Cells(rw, 1)
Else
Set rng = Union(rng, .Cells(rw, 1))
End If
Exit Do
Else
rw = .Columns(1).FindNext(after:=.Cells(rw, 1)).Row
End If
Loop
Next n
Next v
End With
Debug.Print Timer 'check timer before deleting discontiguous rows
If Not rng Is Nothing Then _
rng.EntireRow.Delete
Debug.Print Timer
bm_SafeExit:
Application.Calculation = xlCalculationAutomatic
Application.ScreenUpdating = True
Application.EnableEvents = True
End Sub
By first checking to make sure there is something to delete, some error control can be avoided; you only need to find the entry for the double matching criteria that you know exists.
Addendum: Deleting a collection of discontiguous rows is time consuming. The second routine (delTwofers2) above was 5% slower that the one that deleted rows as they were found. 25,000 values, 755 random deletions - 3.60 seconds for the first; 3.75 seconds for the latter.
This code applies a filter to the first two columns of the used range using your criteria. It then deletes the visible rows:
Sub DeleteSelected()
Dim RangeToFilter As Excel.Range
Set RangeToFilter = ActiveSheet.UsedRange
With RangeToFilter
.AutoFilter Field:=1, Criteria1:="find me"
.AutoFilter Field:=2, Criteria1:="access granted"
.SpecialCells(xlCellTypeVisible).EntireRow.Delete Shift:=xlUp
End With
End Sub
I am getting a runtime error 1004 if I'm not on the same page that the script is meant to run on, and I'd like to know why...
here is the code.
Option Explicit
Sub PO_Tracking()
Dim wsPOD As Worksheet
Dim wsPOT As Worksheet
Dim wsPOA As Worksheet
Dim cel As Range
Dim lastrow As Long, i As Long, Er As Long
Set wsPOD = Sheets("PO Data")
Set wsPOT = Sheets("PO Tracking")
Set wsPOA = Sheets("PO Archive")
With Application
.ScreenUpdating = False
.DisplayAlerts = False
.EnableEvents = False
.Calculation = xlCalculationManual
End With
With wsPOD
'first bring columns F:G up to match their line
For Each cel In Intersect(.UsedRange, .UsedRange.Offset(5), .Columns(6))
If cel = vbNullString And cel.Offset(, -2) <> vbNullString Then
.Range(cel.Offset(1), cel.Offset(1, 1)).Copy cel
cel.Offset(1).EntireRow.Delete
End If
Next
'now fil columns A:D to match PO Date and PO#
For Each cel In Intersect(.UsedRange, .UsedRange.Offset(5), .Columns(1))
If cel = vbNullString And cel.Offset(, 5) <> vbNullString Then
.Range(cel.Offset(-1), cel.Offset(-1, 3)).Copy cel
End If
Next
'Blow away rows that are useless
lastrow = wsPOD.Range("A6").End(xlDown).Row
wsPOD.Range("M5:P5").Copy wsPOD.Range("M6:P" & lastrow)
Calculate
With Intersect(wsPOD.UsedRange, ActiveSheet.Columns("N"))
.AutoFilter 1, "<>Different"
.SpecialCells(xlCellTypeVisible).EntireRow.Delete
End With
With Intersect(wsPOD.UsedRange, ActiveSheet.Columns("P"))
.AutoFilter 1, "<>Full"
.SpecialCells(xlCellTypeVisible).EntireRow.Delete
End With
wsPOD.UsedRange.Copy Sheets.Add.Range("A1")
'Final Adjustments before transfering over to new sheet.
With ActiveSheet
.AutoFilterMode = False
Intersect(.UsedRange, .Columns("A")).Cut .Range("Q1")
Intersect(.UsedRange, .Columns("D")).Cut .Range("R1")
Intersect(.UsedRange, .Columns("C")).Cut .Range("S1")
Intersect(.UsedRange, .Columns("B")).Cut .Range("T1")
Intersect(.UsedRange, .Columns("G")).Cut .Range("U1")
Intersect(.UsedRange, .Columns("F")).Cut .Range("V1")
Intersect(.UsedRange, .Range("Q:V")).Copy wsPOT.Cells(Rows.Count, "B").End(xlUp).Offset(1)
.Delete
End With
lastrow = wsPOD.Cells(Rows.Count, "B").End(xlUp).Row
wsPOT.Range("R1:X1").Copy
wsPOT.Range("B3:H" & lastrow).PasteSpecial xlPasteFormats
wsPOT.Range("N2:O2").Copy wsPOT.Range("N3:O" & lastrow)
wsPOT.Range("P1:Q1").Copy wsPOT.Range("I3:J" & lastrow)
wsPOT.Range("K3:K" & lastrow).Borders.Weight = xlThin
End With
Application.CutCopyMode = False
End Sub
The error is here:
**With Intersect(wsPOD.UsedRange, ActiveSheet.Columns("N"))**
.AutoFilter 1, "<>Different"
.SpecialCells(xlCellTypeVisible).EntireRow.Delete
End With
You can't have an intersection of ranges on two sheets, so if ActiveSheet is not wsPOD, then
With Intersect(wsPOD.UsedRange, ActiveSheet.Columns("N"))
has to fail by definition.
EDIT ... and see #SiddharthRout's comment for the fix.
For why the error, see the answer by Doug Glancy.
In addition, for how to avoid it, use something like
Dim rng1 As Range, rng2 As Range
Set rng1 = wsPOD.UsedRange
Set rng2 = ActiveSheet.Columns("N")
If (rng1.Parent.Name = rng2.Parent.Name) Then
Dim ints As Range
Set ints = Intersect(rng1, rng2)
If (Not (ints Is Nothing)) Then
With ints
' Do your job
End With
End If
End If
It is typically good practice to verify an Intersection before using it.
to avoid the error one has to check for equality of the worksheet (myRange.Parent) like this:
if rng1.Parent is rng2.Parent then if Not Intersect( rng1, rng2 ) Is Nothing then _
'... your conditional code here ...
hint: the important thing to notice here is that you can't connect the two conditions with ... And ... since VBA evaluates all conditions and does not stop after evaluating the first even if it is False :-/
or make sure the range's worksheets are the same (e.g. ws1), meaning to explicitely specify/create/intersect your Range objects similar to this):
if Not Intersect( ws1.Range("A1:A2"), ws1.Range("A2:B2") ) Is Nothing then _
'... your conditional code here ...