Application.Match mismatch error 13 - How to resolve? - vba

I have been working on some code that goes through and tries to find "New Muted Price" or "New Opposed Price". If that is not found during the array iteration, it comes up with a
Mismatch error run code 13
I know this is because it did not find it, but how do I just get it to skip past the error and continue with the code? I have tried
if not iserror (PriceCol = Application.Match("New Opposed Price", rng, 0)) then but it is still showing the mismatch error.
The portions of the code where the error comes up is:
PriceCol = Application.Match("New Opposed Price", rng, 0)
and
pricecol2 = Application.Match("New Muted Price", rng, 0)
Does anyone have some advise on how to resolve this issue?
Sub WIP()
Dim wb As Workbook
Dim wsMain As Worksheet
Dim wsLookup As Worksheet
Dim rng As Range
Dim rng2 As Range
Dim rFind1 As Range
Dim rFind2 As Range
Dim rFind3 As Range
Dim MyArray As Variant
Dim LookupHeaders As Variant
Dim LookupHeaders2 As Variant
Dim LR As Long
Dim i As Long
Dim PriceCol As Long
Dim pricecol2 As Long
Dim LastColumn As Long
Dim LastColumn2 As Long
Dim LastColumn3 As Long
Dim LastColumn4 As Long
Dim IndexCol As Long
'Unformatted Price Row
Sheets("Consolidate List").Select
LR = Range("A" & Rows.Count).End(xlUp).Row
Columns("H:H").Select
Selection.Insert Shift:=xlToRight, CopyOrigin:=xlFormatFromLeftOrAbove
Columns("J:N").Delete
Columns("J:J").Select
ActiveWindow.FreezePanes = True
Range("H2").Select
ActiveCell.FormulaR1C1 = "New Price"
ActiveCell.Interior.ColorIndex = 22
Range("H3:H" & LR).Formula = "=VLOOKUP(RC[-7],'Connect Report'!C[-7]:C[-6],2,FALSE)"
ActiveCell.EntireColumn.Resize(Rows.Count - 2).Offset(2).Select
Selection.Copy
Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
Range("I2").Select
ActiveCell.FormulaR1C1 = "Difference"
ActiveCell.Interior.ColorIndex = 22
Range("I3:I" & LR).Formula = "=IF(OR(OR(RC[-2]="""",RC[-1]="""",RC[-1]=""x"",)),"""",RC[-1]-RC[-2])"
ActiveCell.EntireColumn.Resize(Rows.Count - 2).Offset(2).Select
Selection.Copy
Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
Set wb = ActiveWorkbook
Sheets("Consolidate List").Select
Set wsMain = wb.ActiveSheet
Set wsLookup = wb.Sheets("Connect Report") '<-- Change to correct sheet name for the Lookup sheet
LR = wsMain.Cells(wsMain.Rows.Count, "A").End(xlUp).Row
MyArray = Array("US", "SPAIN", "California")
LookupHeaders = Array("TTIER", "Time333", "Round6")
LookupHeaders2 = Array("TELLER5", "Fly7", "Mine4")
For i = LBound(MyArray) To UBound(MyArray)
With wsMain.Rows(1)
Set rFind1 = .Find(What:=MyArray(i), LookAt:=xlWhole, MatchCase:=False, SearchFormat:=False)
If Not rFind1 Is Nothing Then
Set rng = rFind1.Offset(1).Resize(, 8)
PriceCol = Application.Match("New Opposed Price", rng, 0)
LastColumn = rFind1.Column + PriceCol
If wsMain.Cells(rng.Row, LastColumn) <> "New Opposed Price" Then
wsMain.Columns(LastColumn).Insert Shift:=xlToRight, CopyOrigin:=xlFormatFromLeftOrAbove
wsMain.Cells(rng.Row, LastColumn).Value = "New Opposed Price"
wsMain.Cells(rng.Row, LastColumn).Interior.ColorIndex = 22
LastColumn2 = LastColumn + 1
wsMain.Columns(LastColumn2).Insert Shift:=xlToRight, CopyOrigin:=xlFormatFromLeftOrAbove
wsMain.Cells(rng.Row, LastColumn2).Value = "Difference"
wsMain.Cells(rng.Row, LastColumn2).Interior.ColorIndex = 22
Set rFind2 = wsLookup.Rows(1).Find(LookupHeaders(i), wsLookup.Range("A1"), xlValues, xlWhole)
If Not rFind2 Is Nothing Then
IndexCol = rFind2.Column
wsMain.Cells(rng.Row + 1, LastColumn).Resize(LR - 2).Formula = "=VLOOKUP(A" & rng.Row + 1 & ",'Connect Report'!$A:$AL," & IndexCol & ",FALSE)"
wsMain.Cells(rng.Row + 1, LastColumn2).Resize(LR - 2).Formula = "=IF(OR(OR(RC[-2]="""",RC[-1]="""",RC[-1]=""x"",)),"""",RC[-1]-RC[-2])"
Else
MsgBox "Excel could not find " & LookupHeaders(i) & " in the lookup table."
End If
Set rng2 = rFind1.Offset(1).Resize(, 8)
pricecol2 = Application.Match("New Muted Price", rng, 0)
LastColumn3 = rFind1.Column + pricecol2
If wsMain.Cells(rng.Row, LastColumn3) <> "New Muted Price" Then
wsMain.Columns(LastColumn3).Insert Shift:=xlToRight, CopyOrigin:=xlFormatFromLeftOrAbove
wsMain.Cells(rng2.Row, LastColumn3).Value = "New Muted Price"
wsMain.Cells(rng2.Row, LastColumn3).Interior.ColorIndex = 22
LastColumn4 = LastColumn3 + 1
wsMain.Columns(LastColumn4).Insert Shift:=xlToRight, CopyOrigin:=xlFormatFromLeftOrAbove
wsMain.Cells(rng2.Row, LastColumn4).Value = "Difference"
wsMain.Cells(rng2.Row, LastColumn4).Interior.ColorIndex = 22
End If
Set rFind3 = wsLookup.Rows(1).Find(LookupHeaders2(i), wsLookup.Range("A1"), xlValues, xlWhole)
If Not rFind3 Is Nothing Then
IndexCol = rFind3.Column
wsMain.Cells(rng2.Row + 1, LastColumn3).Resize(LR - 2).Formula = "=VLOOKUP(A" & rng2.Row + 1 & ",'Connect Report'!$A:$AL," & IndexCol & ",FALSE)"
wsMain.Cells(rng2.Row + 1, LastColumn4).Resize(LR - 2).Formula = "=IF(OR(OR(RC[-2]="""",RC[-1]="""",RC[-1]=""x"",)),"""",RC[-1]-RC[-2])"
Else
MsgBox "Excel could not find " & LookupHeaders2(i) & " in the lookup table."
End If
End If
End If
End With
Next i
End Sub

You're on the right track using Application.Match (which can return an Error object) versus WorksheetFunction.Match (which always raises the error).
But since your PriceCol and PriceCol2 variables are strongly typed as Long, you'll get a Mismatch error.
Use another throwaway variable to handle the return:
Dim matchVal as Variant
matchVal = Application.Match("New Muted Price", rng, 0)
If Not IsError(matchVal) Then
PriceCol2 = matchVal
...
Else
' if there is no match, you may need to do something else here.
End If
Alternatively, you could use the Range.Find method:
If Not rng.Find("New Muted Price") Is Nothing
PriceCol2 = Application.Match("New Muted Price", rng, 0)
Else
...

Related

Excel VBA: Finding last row

I am trying to find the last row of a set of numbers for each column, however it seems my code is using the same last row as the previous column's last row.
Here is the first column's code:
Dim WorkRng As Range
xTitleId = "Select Total Sales cell"
Set WorkRng = Application.Selection
Set WorkRng = Application.InputBox("Range", xTitleId, WorkRng.Address, Type:=8)
WorkRng.Select
Selection.Copy
Range("A65") = "Total Sales"
Range("A66").Select
Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
Set WorkRng = Range("A66")
Here is the adjacent column's code:
Dim WorkRng2 As Range
xTitleId2 = "Select Collected Range"
Set WorkRng2 = Application.Selection
Set WorkRng2 = Application.InputBox("Range", xTitleId2, WorkRng2.Address, Type:=8)
WorkRng2.Select
Selection.Copy
Range("B65") = "Collected Range"
Range("B66").Select
Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
Range("B66:B100").Select
Selection.SpecialCells(xlCellTypeBlanks).Select
Selection.Delete Shift:=xlUp
Range("B66").Select
Dim LastRow2 As Long
LastRow2 = Cells(Rows.Count, 1).End(xlUp).Row
Range("B" & LastRow2).Offset(1, 0).Formula = "=SUM(B66:B" & LastRow2 & ")"
Range("B" & LastRow2).Offset(1, 0).Select
Set WorkRng2 = Range("B" & LastRow2).Offset(1, 0)
It keeps saying that LastRow2 is 66, however I would like it to be dynamic and independent of the first column's last row.
Any help is greatly appreciated
You can add a VBA Function like the below:
Function GetLastRow(wsTarget As Worksheet, iCol)
'Gets the last non-blank cell
Dim lrow As Long, Max_Row
Max_Row = 1048576
On Error GoTo SmallFile
TryAgain:
With wsTarget
lrow = .Cells(Max_Row, iCol).End(xlUp).Row
End With
GetLastRow = lrow
Exit Function
SmallFile:
Max_Row = 65536
On Error GoTo 0
GoTo TryAgain
End Function
Then you specificy the worksheet and column number you're after. i.e. GetLastRow(worksheets("Sheet1"),1) would return the last row for Column A in the Sheet1 tab.
Beware of the fact, that xlUp gets last visible row, which can cause problems, if filters are present. Therefore, if filters might be active, use rather:
Function getLastRow(col As String, ws As Worksheet) As Long
Call removeFilters(ws)
getLastRow = ws.Range(col & Rows.Count).End(xlUp).Row
End Function
Sub removeFilters(ws As Worksheet)
On Error Resume Next
ws.ShowAllData
End Sub
example of use:
dim rng as Range
Set rng = Range("B1:B" & getLastRow("B", ActiveWorksheet))

Excel VBA - Find all cells with value and delete the entire row if it exist

This is my first time asking a question on here. I have dug through similar questions, but have had no luck yet in resolving this quandary. I appreciate any help you can give me.
In the data set I am working with, I am looking to delete any rows that contain the word "Bench" in column R. I already have the rest of the worksheet running and have the Lrow value set as the last row.
I was first successful using the .Setfilter, selecting the range, and using EntireRow.Delete. But this ended up deleting the entire dataset if there were no rows to select.
To summarize the ask: Looking in Range("R2":"R" & Lrow), find all cells containing the text "Bench", then Delete the row.
Thank you!
Here is the entire VBA as sits right now (this bit is near the bottom):
Sub BE_Time_to_Fill()
'
' BE_Time_to_Fill Macro
'
Dim StartCell As Range
Dim RangeName As String
Dim myValue As Variant
Set StartCell = Range("A1")
myValue = InputBox("Enter Date: YY-MMM")
'Select Range
StartCell.CurrentRegion.Select
RangeName = "Dataset"
Dim LRow As Long
Dim lCol As Long
'Find the last non-blank cell in column A(1)
LRow = Cells(Rows.Count, 1).End(xlUp).Row
'Find the last non-blank cell in row 1
lCol = Cells(1, Columns.Count).End(xlToLeft).Column
Columns("J:J").Insert Shift:=xlToRight, CopyOrigin:=xlFormatFromLeftOrAbove
Range("J1").FormulaR1C1 = "Time to Fill"
Range("J2", "J" & LRow).FormulaR1C1 = "=RC[1]+RC[2]"
Range("F1").Select
Range("F1").FormulaR1C1 = "Job Code"
Range("F1", "F" & LRow).AutoFilter 1, ""
Range("F2", "F" & LRow).FormulaR1C1 = "=RC[-1]"
[F1].AutoFilter
Range("M1").FormulaR1C1 = "Source Time"
Columns("N:N").Insert Shift:=xlToRight, CopyOrigin:=xlFormatFromLeftOrAbove
Range("N1").FormulaR1C1 = "Cycle Time"
Range("N2", "N" & LRow).FormulaR1C1 = "=IMSUB(RC[1],RC[-1])"
Columns("A:A").Insert Shift:=xlToRight, CopyOrigin:=xlFormatFromLeftOrAbove
Range("A1").FormulaR1C1 = "Application ID"
Range("A2", "A" & LRow).FormulaR1C1 = "=CONCATENATE(RC[1],RC[4])"
Cells.Select
Selection.Copy
Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
Application.CutCopyMode = False
Columns("B:B").Insert Shift:=xlToRight, CopyOrigin:=xlFormatFromLeftOrAbove
Range("B1").FormulaR1C1 = "Timeframe"
Range("B2", "B" & LRow).Value = myValue
Dim rng As Range
Dim DelRng As Range
Set DelRng = Range("R2:R" & LRow)
For Each rng In DelRng
If rng.Value = "*Bench" Then
rng.EntireRow.Delete
ElseIf rng.Value <> "*Bench" Then
End If
Next
Range("G:H,M:N").Delete Shift:=xlToLeft
Range("A1").Select
End Sub
Without seeing what code you have we can't help update it. But from your question the below might help.
If you're using a loop you'll need to include what to do if the set conditions aren't met. See example:
Sub example()
Dim rng As Range, DelRng As Range
Dim LastRow As Long
LRow = Range("R" & Rows.Count).End(xlUp).Row 'test for last filled row in column R
Set DelRng = Range("R1:R" & LRow) 'sets your range
For Each rng In DelRng
'change this value to match whatever you want to find. make sure this is entered as ALL CAPS and without spaces
If UCase(WorksheetFunction.Substitute(rng.Value, " ", "")) = "GEM/BENCH" Then
rng.EntireRow.Delete
ElseIf UCase(WorksheetFunction.Substitute(rng.Value, " ", "")) <> "GEM/BENCH" Then 'if loop can't find anything it will just exit
End If
Next
End Sub

VBA: Looking for a value and copy and paste the value in a other sheet

I have a problem with my VBA code. The problem is that I have duplicate names - the main sheet "Manager" and the names of the sheets.
The code should go to every sheet and look for the value "Engagements ID" and then go one cell down. In every sheet the number of Engagements ID is different, so the code should search in every sheet (500 rows) - look for the value "Engagements ID" then copy and paste the cell what is one row below into my main sheet, which is called "Manager".
Thank you for help!! :) The value what I looking for is on every sheet in column B.
This is my code:
Option Explicit
Sub Check_Account()
Dim rng As Range
Dim xName As String
Dim i, j As Integer
For i = 3 To 6
xName = Cells(i, 1)
If xName = "" Then Exit Sub
On Error Resume Next
ActiveWorkbook.Sheets(xName).Select
Sheets(xName).Select
For j = 1 To 500
If rng.Cells(j, 2) = "Engagements ID" Then
rng.Offset(1, 0).Select
Selection.Copy
Sheets("Manager").Select
If Range("B" & i) = "" Then
Range("B" & i).Select
Selection.PasteSpecial Paste:=xlPasteValues,
Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
ActiveWorkbook.Sheets(xName).Select
Sheets(xName).Select
Cells(j, 2).Offset(1, 0).Select
Else
Range("B" & i).Offset(1, 0).Select
Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
ActiveWorkbook.Sheets(xName).Select
Sheets(xName).Select
Cells(j, 2).Offset(1, 0).Select
End If
End If
Next j
On Error GoTo 0
Next i
End Sub
Please try this code. I think you will like it.
Option Explicit
Sub Check_Account()
' 24 Nov 2017
Dim TabName As String
Dim Rng As Range
Dim Fnd As Range
Dim Rl As Long ' last row
Dim FirstFnd As Long
Dim i As Integer
For i = 3 To 6
' Tab names are found at Manager!A3:A6
TabName = Worksheets("Manager").Cells(i, "A").Value
If Len(TabName) = 0 Then Exit For
On Error Resume Next
With Worksheets(TabName)
If Err Then
MsgBox "Worksheet """ & TabName & """ doesn't exist.", _
vbInformation, "Missing Worksheet"
Else
Rl = .Cells(.Rows.Count, "B").End(xlUp).Row
Set Rng = Range(.Cells(1, "B"), .Cells(Rl, "B"))
Set Fnd = Rng.Find("Engagements ID", _
After:=Rng.Cells(Rng.Cells.Count), _
LookIn:=xlValues, _
LookAt:=xlPart, _
SearchOrder:=xlByColumns, _
SearchDirection:=xlNext, _
MatchCase:=False, _
MatchByte:=False)
If Not Fnd Is Nothing Then
FirstFnd = Fnd.Row
Do
With Worksheets("Manager")
Rl = .Cells(.Rows.Count, "B").End(xlUp).Row + 1
' start writing in row 2
If Rl < 2 Then Rl = 2
.Cells(Rl, "B").Value = Fnd.Offset(1).Value
End With
Set Fnd = Rng.FindNext(Fnd)
Loop While Not Fnd Is Nothing And Fnd.Row <> FirstFnd
End If
End If
End With
Next i
End Sub
I have tried and tested the code below, and I believe it does what you expected it to do:
Sub foo()
For i = 3 To 6
xName = Sheets("Manager").Cells(i, 1).Value
LastRow = Sheets(xName).Cells(Sheets(xName).Rows.Count, "B").End(xlUp).Row
For x = 1 To LastRow
If Sheets(xName).Cells(x, 2).Value = "Engagements ID" Then
Sheets("Manager").Cells(i, 2).Value = Sheets(xName).Cells(x + 1, 2).Value
End If
Next x
Next i
End Sub
This does not have any validation against possible errors, if the manager sheet does not exist, then you will get an error... But at least the code is more concise and it points you in the right direction.

VBA check if columns are the same

I have two Sheets in Excel that I need to check if the columns are the same in both sheets before processing them.
I have created a macro to do this check, but I'm wondering if there is a better way to achieve this.
Sub CheckColumns()
Sheets("Source1").Select
Range("A1").Select
Range(Selection, Selection.End(xlToRight)).Select
Selection.Copy
Sheets("Sheet1").Select
Range("A1").Select
ActiveSheet.Paste
Sheets("Source2").Select
Range("A1").Select
Range(Selection, Selection.End(xlToRight)).Select
Selection.Copy
Sheets("Sheet1").Select
Range("A2").Select
ActiveSheet.Paste
Range("A3") = "=IF(A1=A2,0,1)"
Range("A3").Copy
Range("A2").Select
Selection.End(xlToRight).Select
ActiveCell.Offset(1, 0).Range("A1").Select
Range(Selection, Selection.End(xlToLeft)).Select
ActiveSheet.Paste
Range("A4") = "=SUM(3:3)"
If Range("A4").Value = 0 Then
MsgBox "Same Columns"
Else
MsgBox "different Columns"
End If
End Sub
First of all you need to avoid selection; How to avoid using Select in Excel VBA macros
Specificaally about your code; I would try comparing two arrays as it always faster to work with arrays and also it doesn't need a dummy-sheet. However, your approach, except the selection part is faster in my mind. So I would include the explicit version of your approach shortly.
Sub CheckColumns()
Dim arrS1 As Variant, arrS2 As Variant
Dim LastRow As Long
With Worksheets("Source1")
LastRow = .Cells(.Rows.Count, "A").End(xlUp).Row
arrS1 = .Range("A1:A" & LastRow)
End With
With Worksheets("Source2")
LastRow = .Cells(.Rows.Count, "A").End(xlUp).Row
arrS2 = .Range("A1:A" & LastRow)
End With
If UBound(arrS1) <> UBound(arrS2) Then
MsgBox "Different Columns"
Exit Sub
End If
same = True
For i = LBound(arrS1) to UBound(arrS1)
If arrS1(i) <> arrS1(i) Then
same = False
Exit For
End If
Next i
If same = True Then
MsgBox "Same Column"
Else
MsgBox "Item " & i & " does not match. Stopped checking further"
End If
End Sub
This is the explicit version of your method:
Sub CheckColumns()
Dim rngrS1 As Range, rngS2 As Range, rngSH As Range
Dim LastRow1 As Long, LastRow2 As Long
With Worksheets("Source1")
LastRow1 = .Cells(.Rows.Count, "A").End(xlUp).Row
Set rngS1 = .Range("A1:A" & LastRow)
End With
With Worksheets("Source2")
LastRow2 = .Cells(.Rows.Count, "A").End(xlUp).Row
Set rngS2 = .Range("A1:A" & LastRow)
End With
If LastRow1 <> LastRow2 Or rngS1(1) <> rngS2(1) Then
'Second condition checks names of the columns
MsgBox "Different Columns"
Exit Sub
End If
With Worksheets("Sheet1")
Set rngSH = .Range("A1:A" & LastRow1)
End With
rngSH.Value = rngS1.Value
Set rngSH = rngSH.Offset(0,1)
rngSH.Value = rngS2.Value
Set rngSH = rngSH.Offset(0,1)
rngSH.formula "=IF(A1=B1,0,1)"
Worksheets(Sheet1).Range("D2") = "Sum(C:C)"
If Worksheets(Sheet1).Range("D2").Value <> 0 Then
MsgBox "Different Columns"
Else
MsgBox "Same Columns"
End If
End Sub
You could declare two arrays and compare that way...
Sub Compare()
Dim FirstSheet As Variant, SecondSheet As Variant
Dim a As Long, b As Long
FirstSheet = Sheets("Source1").Range("A1:" & _
Mid(Sheets("Source1").Range("A1").End(xlToRight).Address, 2, _
InStr(Right(Sheets("Source1").Range("A1").End(xlToRight).Address, _
Len(Sheets("Source1").Range("A1").End(xlToRight).Address) - 2), "$")) & 1)
SecondSheet = Sheets("Source2").Range("A1:" & _
Mid(Sheets("Source2").Range("A1").End(xlToRight).Address, 2, _
InStr(Right(Sheets("Source2").Range("A1").End(xlToRight).Address, _
Len(Sheets("Source2").Range("A1").End(xlToRight).Address) - 2), "$")) & 1)
On Error Resume Next
For a = 1 To WorksheetFunction.Max(Sheets("Source1").Range("A1:" & _
Mid(Sheets("Source1").Range("A1").End(xlToRight).Address, 2, _
InStr(Right(Sheets("Source1").Range("A1").End(xlToRight).Address, _
Len(Sheets("Source1").Range("A1").End(xlToRight).Address) - 2), "$")) & 1).Cells.Count, _
Sheets("Source1").Range("A1:" & Mid(Sheets("Source1").Range("A1").End(xlToRight).Address, 2, _
InStr(Right(Sheets("Source1").Range("A1").End(xlToRight).Address, _
Len(Sheets("Source1").Range("A1").End(xlToRight).Address) - 2), "$")) & 1))
If FirstSheet(1, a) <> SecondSheet(1, a) Then b = b + 1
Next
On Error GoTo 0
If b = 0 Then
MsgBox "Same Columns"
Else
MsgBox "different Columns"
End If
End Sub

Show Whole Table After Null Search

for the code below, if a search comes up empty based on Criteria1:="Ship", then there is nothing to copy, and the code stops at Set rngCopy = Intersect(rngCopy, .Range("A1:H" & lRow), .Range("A1:H" & lRow).Offset(1)).SpecialCells(xlCellTypeVisible), how can I get rid of this bug? Additionally, I want the whole table to show even if no data meets the criteria. I have the line Worksheets("Efficiency").ShowAllData but this is under the assumption the code runs all the way.
Thanks,
Sub ImportShipper()
Dim wsEff As Worksheet
Dim wsShip As Worksheet
Dim wsFirst As Worksheet
Set wsEff = Worksheets("Efficiency")
Set wsFirst = Worksheets("1")
Set wsShip = ActiveSheet
wsShip.Name = wsFirst.Range("B34").Value
With wsEff
Dim lRow As Long
lRow = .Range("A" & .Rows.Count).End(xlUp).Row
.Range("A1:H" & lRow).AutoFilter Field:=2, Criteria1:="Ship"
Dim rngCopy As Range
'All Columns A:H
Set rngCopy = .Columns("A:H")
'filtered rows, not including header row - assumes row 1 is headers
Set rngCopy = Intersect(rngCopy, .Range("A1:H" & lRow), .Range("A1:H" & lRow).Offset(1)).SpecialCells(xlCellTypeVisible)
rngCopy.Copy
End With
wsShip.Range("A4").PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
Worksheets("Efficiency").ShowAllData
End Sub
you could go like this
Option Explicit
Sub ImportShipper()
Dim wsEff As Worksheet
Dim wsShip As Worksheet
Dim wsFirst As Worksheet
Set wsEff = Worksheets("Efficiency")
Set wsFirst = Worksheets("1")
Set wsShip = ActiveSheet
wsShip.Name = wsFirst.Range("B34").value
With wsEff
Dim lRow As Long
lRow = .Range("A" & .Rows.Count).End(xlUp).Row
With .Range("A1:H" & lRow)
.AutoFilter Field:=2, Criteria1:="Ship"
With .Offset(1).Resize(.Rows.Count - 1)
If Application.WorksheetFunction.Subtotal(103, .Columns(2)) > 0 Then
.SpecialCells(xlCellTypeVisible).Copy
wsShip.Range("A4").PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks:=False, Transpose:=False
End If
End With
End With
End With
Worksheets("Efficiency").ShowAllData
End Sub