【问题标题】:Excel vba - Compare two ranges and find non matchesExcel vba - 比较两个范围并查找不匹配项
【发布时间】:2011-10-12 11:40:36
【问题描述】:

我有两张 Excel 表格,其中一张包含用户列表。而另一个列表包含相同的数据,只是同一个用户被列出了几次。现在,我需要某种方法将第二个列表与第一个列表进行比较,并删除包含在第一个列表中未找到的用户的行。

第一个列表如下所示:

  • 保罗·麦卡特尼
  • 约翰·列侬
  • 乔治·哈里森
  • 林戈·斯塔尔

第二个列表可能如下所示:

  • 保罗·麦卡特尼
  • 保罗·麦卡特尼
  • 保罗·麦卡特尼
  • 约翰·列侬
  • 约翰·列侬
  • 约翰·列侬
  • 乔治·哈里森
  • 乔治·哈里森
  • 乔治·哈里森
  • 林戈·斯塔尔
  • 林戈·斯塔尔
  • 林戈·斯塔尔
  • 林戈星
  • 林戈之星
  • 林戈星

因此,比较这两个列表,您会看到名称 Ringo Star 不在第一个列表中,我想删除这些行。我已经尝试了几个循环,但我不能让它工作。我想我可以将这些项目添加到某种数组中,并通过函数运行它。但是,没有那么多代码,有没有一种简单的方法可以做到这一点?

【问题讨论】:

    标签: excel compare


    【解决方案1】:

    这一次,你可以使用一个集合。

    这是基于您之前的文件的尝试:

    Option Explicit
    
    Sub test()
    Dim i As Long
    Dim arrSum As Variant, arrUsers As Variant
    Dim cUnique As New Collection
    
    'Put the name range from "Summary" in an array
    With ThisWorkbook.Sheets("Summary")
        arrSum = .Range("A2", .Range("A" & Rows.Count).End(xlUp))
    End With
    
    '"Convert" the array to a collection (unique items)
    For i = 1 To UBound(arrSum, 1)
        On Error Resume Next
        cUnique.Add arrSum(i, 1), CStr(arrSum(i, 1))
    Next i
    
    'Get the users array
    With ThisWorkbook.Sheets("Users")
        arrUsers = .Range("A2", .Range("A" & Rows.Count).End(xlUp))
    End With
    
    'Check if the value exists in the Users sheet
    For i = 1 To cUnique.Count
        'if can't find the value in the users range, delete the rows
        If Application.WorksheetFunction.VLookup(cUnique(i), arrUsers, 1, False) = "#N/A" Then
            With ThisWorkbook.Sheets("Summary").Cells
                .AutoFilter Field:=1, Criteria1:=cUnique(i)
                .Range("A2", .Range("A" & Rows.Count).End(xlUp)).EntireRow.Delete
            End With
        End If
    Next i
    'removes AutoFilter if one remains
    ThisWorkbook.Sheets("Summary").AutoFilterMode = False
    End Sub
    

    【讨论】:

    • 再次感谢!这真的很好:) 我看到这里有一些对我来说是新的概念,尤其是比较部分。我会研究并分解你的代码,以确保我能理解它的各个方面:)
    • 我的+1以及变体循环/收集非常有效
    【解决方案2】:

    您可以使用简单的 MATCH 公式来检测任何不匹配的内容,然后使用 AutoFilter 将其删除

    如果您的第一个列表在工作表 1 的 A 列中,则您的第二个列表在工作表 2 的 A 列中,然后在工作表 2 的 B1 中放置 =ISNA(匹配(A1,Sheet1!A:A,0)) 然后抄下来

    如果第二个列表不能与第一个匹配,则返回 TRUE。然后,您可以使用自动过滤器删除这些 TRUE 行

    请注意,您也可以使用 =COUNTIF(Sheet1!A:A,A1)=0 为了相同的效果来识别不匹配(如 TRUE)

    这里显示的是xl2010图片

    [已添加 VBA]

    Sub QuickKill()
        Dim ws1 As Worksheet
        Dim ws2 As Worksheet
        Dim rng1 As Range
        Set ws1 = Sheets(1)
        Set ws2 = Sheets(2)
        ws2.Columns(2).Insert
        Set rng1 = ws2.Range(ws2.[a1], ws2.Cells(Rows.Count, "A").End(xlUp))
        Rows(1).Insert
        With rng1.Offset(0, 1)
            .FormulaR1C1 = "=COUNTIF('" & ws1.Name & "'!C1,RC[-1])=0"
            .AutoFilter Field:=1, Criteria1:="TRUE"
            .EntireRow.Delete
            .EntireColumn.Delete
        End With
    End Sub
    

    【讨论】:

    • 啊,我知道这行得通:) 但我认为我确实需要通过 VBA。因为我希望这个列表尽可能纯净,那么我将如何使用 VBA 来做到这一点?我可以将这个公式从上到下添加到一个空列中吗?然后遍历每个单元格,找到值 TRUE,然后使用 vba 代码删除这些行?或者我可以使用该公式运行 IF 并直接检查值吗?
    • 我认为没有 vba 是非常小的 VB :)。上面的 VBA 自动执行相同的操作,即使用工作公式列而不是循环非常快速地删除。
    • 这是一个非常明确的答案。你可能是对的,使用公式会比循环更快。 +1 顺便说一句
    【解决方案3】:

    this question。使用该技术,您可以轻松查询SELECT * FROM [Sheet2$] WHERE columnX NOT IN (SELECT columnY FROM [Sheet1$]

    【讨论】:

      猜你喜欢
      • 2011-12-12
      • 2021-12-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-12-24
      相关资源
      最近更新 更多