Deleting Duplicate Rows With Advanced Filter
This page describes how to use the Advanced Filter tool to delete duplicate rows.
You can use Excel's Advanced Filter tool to delete duplicate rows in a range of data. The function shown
below, DeleteDuplicatesViaFilter, will delete entire rows leaving distinct rows of data. You pass to the function
the range to test for duplicates and the function returns as its result the number of rows deleted, or -1 if an error
occurred.
The range that you pass into the function should contain all the rows you want to test for duplicates, and contain (only) the
columns that are used to determine whether a row is a duplicate. For example, if your data is in rows 1 to 100 and columns D and
E together contain the data that determines whether a row is a duplicate, you would pass in the range D1:E100.
Note that even though the input range is 1 or more columns, entire rows are deleted. The range that you pass to the function must
be contiguous. That is, the columns that determine whether a row is a duplicate must be adjacent. The function will fail if the
input range has more than one area.
Although this procedured is a Function, you cannot call it from a worksheet cell. It is intended to be
called from other VBA procedures. You can use the Sub version of this procedure, callable from the
Macros dialog on the Tools menu, to filter out duplicates by selecting the range to filter and then
executing the Sub procedure. The downloadable module contains both the Sub
and the Function version of the procedure.
Excel's Filter function assumes that the first row of the input range is comprised of column titles, so the first row will
never be deleted and may cause a single duplicate row to be included in the result.
You can download a bas module file here containing the code.
Function DeleteDuplicatesViaFilter(ColumnRangeOfDuplicates As Range) As Long
Dim DeleteRange As Range
Dim Rng As Range
Dim SaveCalc As Long
Dim SaveEvents As Long
Dim SaveUpdating As Long
Dim BeginRowCount As Long
Dim EndRowCount As Long
SaveCalc = Application.Calculation
SaveEvents = Application.EnableEvents
SaveUpdating = Application.ScreenUpdating
On Error GoTo ErrH:
If ColumnRangeOfDuplicates.Areas.Count > 1 Then
DeleteDuplicatesViaFilter = -1
Exit Function
End If
If ColumnRangeOfDuplicates.Worksheet.ProtectContents = True Then
DeleteDuplicatesViaFilter = -1
Exit Function
End If
Application.Calculation = xlCalculationManual
Application.EnableEvents = False
Application.ScreenUpdating = False
BeginRowCount = ColumnRangeOfDuplicates.Rows.Count
ColumnRangeOfDuplicates.AdvancedFilter action:=xlFilterInPlace, unique:=True
For Each Rng In ColumnRangeOfDuplicates
If Rng.EntireRow.Hidden = True Then
If DeleteRange Is Nothing Then
Set DeleteRange = Rng.EntireRow
Else
Set DeleteRange = Application.Union(DeleteRange, Rng.EntireRow)
End If
End If
Next Rng
DeleteRange.Delete shift:=xlUp
ActiveSheet.ShowAllData
EndRowCount = ColumnRangeOfDuplicates.Rows.Count
DeleteDuplicatesViaFilter = BeginRowCount - EndRowCount
ErrH:
If Err.Number <> 0 Then
DeleteDuplicatesViaFilter = -1
End If
Application.Calculation = SaveCalc
Application.EnableEvents = SaveEvents
Application.ScreenUpdating = SaveUpdating
End Function
The code for the Sub version is shown below.
Sub DeleteDuplicatesViaFilterSub()
Dim DeleteRange As Range
Dim Rng As Range
Dim SaveCalc As Long
Dim SaveEvents As Long
Dim SaveUpdating As Long
Dim BeginRowCount As Long
Dim EndRowCount As Long
SaveCalc = Application.Calculation
SaveEvents = Application.EnableEvents
SaveUpdating = Application.ScreenUpdating
On Error GoTo ErrH:
If Not TypeOf Selection Is Range Then
Exit Sub
End If
If Selection.Areas.Count > 1 Then
Exit Sub
End If
If Selection.Worksheet.ProtectContents = True Then
Exit Sub
End If
Application.Calculation = xlCalculationManual
Application.EnableEvents = False
Application.ScreenUpdating = False
BeginRowCount = Selection.Rows.Count
Selection.AdvancedFilter action:=xlFilterInPlace, unique:=True
For Each Rng In Selection
If Rng.EntireRow.Hidden = True Then
If DeleteRange Is Nothing Then
Set DeleteRange = Rng.EntireRow
Else
Set DeleteRange = Application.Union(DeleteRange, Rng.EntireRow)
End If
End If
Next Rng
DeleteRange.Delete shift:=xlUp
ActiveSheet.ShowAllData
ErrH:
Application.Calculation = SaveCalc
Application.EnableEvents = SaveEvents
Application.ScreenUpdating = SaveUpdating
End Sub
This page last updated: 1-December-2007