2012-08-08 94 views
6

刪除重複有人可以請給我一些指點就如何解決以下問題:VBA,從陣列

假設我有數據,在Excel 2010塊,100行3列。

C列包含一些重複,說這開始了1,1,1 2,3,4,5,...,97,98

使用VBA,我想刪除根據列C重複行,以便我留下1,2,3,.....,97,98,即只有98行和3列。

我知道有一個按鈕,我可以在Excel 2010中點擊來做到這一點,但我想在VBA中做到這一點(因爲我試過這個,出於某種原因,隨後與我的其他代碼互相干擾,並給出錯誤結果)。

此外,我想這樣做的陣列,然後將結果粘貼在工作表上,而不是方法,如Application.Worksheetfunction.countif(.....

因此,像:

Dim myarray() as Variant 
myarray=cells(1,1).Currentregion.value 

Dim a as Long 

For a=1 to Ubound(myarray,1) 

    'something here to 

Next a 

回答

5

I answered a similar question這裏是我使用的代碼:

Dim dict As Object 
Dim rowCount As Long 
Dim strVal As String 

Set dict = CreateObject("Scripting.Dictionary") 

rowCount = Sheet1.Range("A1").CurrentRegion.Rows.Count 

'you can change the loop condition to iterate through the array rows instead 
Do While rowCount > 1 
    strVal = Sheet1.Cells(rowCount, 1).Value2 

    If dict.exists(strVal) Then 
    Sheet1.Rows(rowCount).EntireRow.Delete 
    Else 
    'if doing this with an array, then add code in the Else block 
    ' to assign values from this row to the array of unique values 
    dict.Add strVal, 0 
    End If 

    rowCount = rowCount - 1 
Loop 

Set dict = Nothing 

如果你想使用一個數組,然後通過具有相同條件的元素循環(if/else語句)ST atements。如果該項目不存在於字典中,則可以將其添加到字典並將行值添加到另一個數組中。

說實話,我認爲最有效的方法是修改你從宏記錄器得到的代碼。您可以在一行中執行上述功能:

Sheet1.UsedRange.RemoveDuplicates Columns:=3, Header:=xlYes 
+2

這會從工作表中刪除實際的行,而問題是刪除VBA中的重複項。另外,任何行刪除都應該始終從下往上進行,以避免跳過行 – brettdj 2012-08-08 23:12:36

+0

@brettdj這兩個代碼位都可以刪除重複項。提交者希望在VBA中完成它,最好是使用數組(在這種情況下,他/她可以輕鬆地修改循環以遍歷數組的行而不是範圍,然後僅將獨特的元素添加到單獨的數組中)。如果你看看代碼,你會發現行刪除確實是自下而上的('rowCount'得到遞減)。 :) – Zairja 2012-08-09 13:00:34

+0

那麼問題是標題* VBA,從陣列*刪除重複。你提出一個很好的觀點,即你的代碼在你使用'.Count'的時候確實是自下而上的,儘管在這種情況下提問者可能需要指定第一次出現應該保留在頂部還是底部。 – brettdj 2012-08-10 00:39:20

0

字典最多有255個項目,因此如果您有更多值,則需要使用集合。不幸的是,Collection對象沒有.Contains(a)或.Exists(a)方法,但該函數通過使用錯誤編號很好地處理(僞造它):

更正:字典沒有這樣的限制(謝謝Zairja)。我可能一直在使用Integer遍歷我的Dictionary。在任何情況下,該功能可以讓你檢查項目存在的集合,因此,如果它是有用的人,我會離開這裏:

CollContainsItem(col As Collection, val As Variant) As Boolean 

Dim itm As Variant 
On Error Resume Next 

    itm = col.Item(val) 
    CollContainsItem = Not (Err.Number = 5 Or Err.Number = 9) 

On Error GoTo 0 

End Function 

所以,如果你確實需要一個集合,你可以很可能只是更換

dict.Exists(strVal) 

CollContainsItem(coll, strVal) 

並更換

Set dict = CreateObject("Scripting.Dictionary") 

Set coll = CreateObject("Scripting.Collection") 

和使用Zairja的代碼的其餘部分。 (我沒有真正嘗試,但它應該是接近的)

+2

實際上,'Dictionary'對象不限於255個項目。這只是調試器顯示的最大項目數。我相信它只受內存限制(我使用的是Excel 2010,但在2003版本中,我能夠擁有幾十萬個元素的字典)。此外,你要確保如果你使用某種增量變量,確保它是「Long」而不是「Integer」(它會停在256)。 – Zairja 2012-08-08 19:17:35

+0

哦,Excel的整數只能到256?也許這就是我一直的問題! – 2012-08-08 19:31:52

3
Function eliminateDuplicate(poArr As Variant) As Variant 
Dim poArrNoDup() 

    dupArrIndex = -1 
For i = LBound(poArr) To UBound(poArr) 
     dupBool = False 

     For j = LBound(poArr) To i 
      If poArr(i) = poArr(j) And Not i = j Then 
       dupBool = True 
      End If 
     Next j 

     If dupBool = False Then 
      dupArrIndex = dupArrIndex + 1 
      ReDim Preserve poArrNoDup(dupArrIndex) 
      poArrNoDup(dupArrIndex) = poArr(i) 
     End If 
Next i 

eliminateDuplicate = poArrNoDup 
End Function 
+0

請不要編輯其他SO用戶的答案,因爲您在[本版本](http://stackoverflow.com/revisions/19693896/2)中有答案,如果代碼存在問題,評論並讓他們知道。 – Lankymart 2014-08-14 08:33:31

+0

您需要爲i的每個循環設置dupBool爲false – 99moorem 2015-07-22 09:31:31