VBA比较两个列表并删除不同列中具有重复值的行

Posted

技术标签:

【中文标题】VBA比较两个列表并删除不同列中具有重复值的行【英文标题】:VBA compare two lists and remove row with duplicate value in different column 【发布时间】:2021-08-09 02:12:33 【问题描述】:

我有两个包含几列的列表。有些列不同,但许多列相同且顺序不同。

如何比较 List1 和 List2,以及(例如)删除 List1 的第 34 行,因为 List1 的单元格 E34 = List2 的 H10

由于预先确定的格式:List1 从第 12 行开始(第 11 行的标题),而 List2 从第 7 行开始(第 6 行的标题)

Sub ClearDuplicate()

Dim sht1 As Worksheet
Dim sht2 As Worksheet
Dim C1row As Long
Dim C2row As Long
Dim C2TotalRows As Long
Dim SerialNumber As String
Dim NoDups As Long

Set sht1 = Worksheets("Open Report")
Set sht2 = Worksheets("FNDWRR")
sht2.Activate
C2TotalRows = Application.CountA(Range("H:H"))
C1row = 12

Do While sht1.Cells(C1row, 5).Value <> ""

SerialNumber = sht1.Cells(C1row, 5).Value

    For C2row = 7 To C2TotalRows

        If SerialNumber = Cells(C2row, 8).Value Then
            
            sht1.Activate
            Rows(C1row).Delete
            NoDups = NoDups + 1
            C1row = C1row - 1
            sht2.Activate
            Exit For
        
        End If
        
    Next
    
    C1row = C1row + 1

Loop
    
MsgBox NoDups & " Duplicates were removed"

End Sub

【问题讨论】:

我可能会为每一列构建一个Dictionary,并将每个单元格中的.Value 添加为“键”,将行号添加为“值”。然后使用每个字典中的.Keys 进行比较,并根据您的发现,您可以使用存储的行号来删除/编辑/修改工作表。有关一些信息,请参阅this site。 【参考方案1】:

删除重复行 (Application.Match)

以下内容将删除目标工作表中的所有行,其中给定列中的值也在源工作表的给定列中找到。 代码 (deleteDupeRows) 使用两个函数“简化”:refNonEmptyColumngetCombinedRange
Option Explicit

Sub deleteDupeRows()

    ' Source
    Const sName As String = "FNDWRR"
    Const sFirst As String = "H7"
    ' Destination
    Const dName As String = "Open Report"
    Const dFirst As String = "E12"
    ' Workbook
    Dim wb As Workbook: Set wb = ThisWorkbook
    'Debug.Print wb.Name
    
    ' Create a reference to the Source Range.
    Dim sws As Worksheet: Set sws = wb.Worksheets(sName)
    Dim srg As Range: Set srg = refNonEmptyColumn(sws.Range(sFirst))
    If srg Is Nothing Then Exit Sub
    'Debug.Print sws.Name, srg.Address
    
    ' Create a reference to the Destination Range.
    Dim dws As Worksheet: Set dws = wb.Worksheets(dName)
    Dim drg As Range: Set drg = refNonEmptyColumn(dws.Range(dFirst))
    If drg Is Nothing Then Exit Sub
    'Debug.Print dws.Name, drg.Address
    
    ' Combine matching destination cells into a range.
    Dim crg As Range
    Dim dCell As Range
    Dim dCount As Long
    For Each dCell In drg.Cells
        If IsNumeric(Application.Match(dCell.Value, srg, 0)) Then
            Set crg = getCombinedRange(crg, dCell)
            dCount = dCount + 1
        End If
    Next dCell
    
    ' Delete entire rows of matching destination cells in one go.
    If crg Is Nothing Then
        MsgBox "No duplicates found.", vbExclamation, "Dupes"
    Else
        'crg.Worksheet.Activate
        'crg.EntireRow.Select
        'Debug.Print crg.Worksheet.Name, crg.Address
        'Debug.Print crg.Worksheet.Name, crg.EntireRow.Address
        crg.EntireRow.Delete
        If dCount = 1 Then
            MsgBox "1 duplicate removed.", vbInformation, "Dupes"
        Else
            MsgBox dCount & " duplicates removed.", vbInformation, "Dupes"
        End If
    End If

End Sub

Function refNonEmptyColumn( _
    FirstCell As Range) _
As Range
    Const ProcName As String = "refNonEmptyColumn"
    On Error GoTo clearError
    
    If Not FirstCell Is Nothing Then
        With FirstCell.Cells(1)
            Dim lCell As Range
            Set lCell = .Resize(.Worksheet.Rows.Count - .Row + 1) _
                .Find("*", , xlFormulas, , , xlPrevious)
            If Not lCell Is Nothing Then
                Set refNonEmptyColumn = .Resize(lCell.Row - .Row + 1)
            End If
        End With
    End If

ProcExit:
    Exit Function
clearError:
    Debug.Print "'" & ProcName & "': Unexpected Error!" & vbLf _
              & "    " & "Run-time error '" & Err.Number & "':" & vbLf _
              & "        " & Err.Description
    Resume ProcExit
End Function

Function getCombinedRange( _
        ByVal BuiltRange As Range, _
        ByVal AddRange As Range) _
As Range
    Const ProcName As String = "getCombinedRange"
    On Error GoTo clearError
    
    If AddRange Is Nothing Then
        If Not BuiltRange Is Nothing Then
            Set getCombinedRange = BuiltRange
        End If
    Else
        If BuiltRange Is Nothing Then
            Set getCombinedRange = AddRange
        Else
            If AddRange.Worksheet Is BuiltRange.Worksheet Then
                Set getCombinedRange = Union(BuiltRange, AddRange)
            End If
        End If
    End If

ProcExit:
    Exit Function
clearError:
    Debug.Print "'" & ProcName & "': Unexpected Error!" & vbLf _
              & "    " & "Run-time error '" & Err.Number & "':" & vbLf _
              & "        " & Err.Description
    Resume ProcExit
End Function

【讨论】:

我尝试运行您的代码,但出现“下标超出范围(错误 9)”错误 `` ' 创建对源范围的引用。将 sws 调暗为工作表:设置 sws = wb.Worksheets(sName)

以上是关于VBA比较两个列表并删除不同列中具有重复值的行的主要内容,如果未能解决你的问题,请参考以下文章

删除具有一个不同值的重复行[重复]

如何删除R中两列中具有相同值但ID不同的行[重复]

python pandas:删除A列的重复项,保留B列中具有最高值的行

VBA - 查找副本并比较其中哪一个最高

删除熊猫数据框中具有特定值的行[重复]

在列中查找具有重复值的行