2011-10-12 149 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$]