2011-10-12 199 views
3

我有两张Excel工作表,其中一张工作表由用户列表组成。另一个列表包含相同的数据,只有同一个用户多次列出。现在,我需要一些方法将第二个列表与第一个列表进行比较,并删除包含在第一个列表中找不到的用户的行。Excel vba - 比较两个范围并找到不匹配

第一个列表如下:

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

第二个列表可能是这样的:

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

因此,比较这两个名单,你看这个名字林格·斯塔是不是在第一个列表,我想删除这些行。我已经尝试了几个循环,但我无法完成这个工作。我想我可以将这些项目添加到某种数组中,然后通过函数来​​运行它。但是,如果没有那么多的代码,有没有简单的方法呢?

回答

3

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

这是基于以前的文件一试:

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 
+0

再次超越!这工作得非常好:)我看到这里有一些对我来说很新颖的概念,尤其是比较部分。我会研究和分解你的代码,以确保我能理解它的每个方面:) –

+0

从我+1以及变体循环/集合是非常有效的 – brettdj

2

您可以使用一个简单的匹配公式来检测任何的非匹配,然后用自动筛选

删除

如果你的第一个列表是在表1列A,在表2列A你的第二个,然后在表2的B1将 = ISNA(MATCH(A1,Sheet1!A:A,0)) 并向下复制

返回TRUE,其中第二个列表不能与第一个匹配。您可以删除这些真正的行与自动筛选

请注意,您也可以使用 = COUNTIF(Sheet1!答:A,A1)= 0 对于相同的效果,以确定不匹配(如TRUE)此处所示

enter image description here

xl2010 PIC [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 
+0

啊,我看到的作品:)但我确实需要它通过VBA我认为。因为我希望这个列表尽可能纯粹,那么我如何使用VBA来做到这一点?我是否可以将此公式从上到下添加到空列中。然后遍历每个单元格,找到TRUE值,然后使用vba代码删除这些行?或者我可以使用该公式运行IF并直接检查值? –

+0

我以为没有VBBA是很小的VB :)。上面的VBA自动执行相同的操作,即使用工作公式列而非循环快速删除。 – brettdj

+0

这是一个非常明确的答案。你可能是对的,使用公式会比循环更快。 +1 btw – JMax

1

this question。使用这种技术,你可以很容易地查询SELECT * FROM [Sheet2$] WHERE columnX NOT IN (SELECT columnY FROM [Sheet1$]