2012-08-08 6 views
6

Có thể ai đó vui lòng cung cấp cho tôi một số gợi ý về cách giải quyết vấn đề sau:VBA, xóa các bản sao khỏi mảng

Giả sử tôi có khối dữ liệu trong Excel 2010, 100 hàng theo 3 cột.

Cột C chứa một số bản sao, nói rằng nó bắt đầu như 1,1,1 2,3,4,5, ....., 97,98

Sử dụng VBA, tôi muốn loại bỏ các hàng song song, theo cột C, để tôi bị bỏ lại với 1,2,3, ....., 97, 98, tức là chỉ 98 hàng và 3 cột.

Tôi biết có một nút tôi có thể bấm trong Excel 2010 để làm điều đó nhưng tôi muốn làm điều đó trong VBA (vì tôi đã thử điều này và vì lý do nào đó, inteferes với phần còn lại của mã của tôi sau đó và đưa ra không chính xác các kết quả).

Hơn nữa, tôi muốn làm điều đó trong mảng, sau đó dán kết quả trên bảng tính, chứ không phải là phương pháp như Application.Worksheetfunction.countif (.....

Vì vậy, một cái gì đó như:

.
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 

Trả lời

5

I answered a similar question đây là mã tôi đã sử dụng:

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 

Nếu bạn muốn sử dụng một mảng, sau đó lặp qua các yếu tố với cùng điều kiện (if/else) st atements. Nếu mục không tồn tại trong từ điển, thì bạn có thể thêm nó vào từ điển và thêm các giá trị hàng vào một mảng khác.

Thành thật mà nói, tôi nghĩ cách hiệu quả nhất là điều chỉnh mã bạn muốn lấy từ trình ghi macro. Bạn có thể thực hiện các chức năng trên trong một dòng:

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

Điều này xóa các hàng thực tế từ trang tính, trong khi câu hỏi là để loại bỏ các bản sao trong VBA.Thêm bất kỳ xóa hàng nào cũng luôn luôn xảy ra từ dưới lên, để tránh bỏ qua các hàng – brettdj

+0

@brettdj Cả hai bit mã sẽ hoạt động để loại bỏ các bản sao. Người hỏi muốn làm điều đó trong VBA, tốt hơn là với các mảng (trong trường hợp này người đó có thể dễ dàng sửa đổi vòng lặp để lặp qua các hàng của mảng thay vì một dãy, sau đó chỉ thêm các phần tử duy nhất vào một mảng riêng biệt). Nếu bạn nhìn vào mã, bạn sẽ thấy rằng xóa hàng đi từ dưới lên ('rowCount' được giảm dần). :) – Zairja

+0

Vâng câu hỏi có tiêu đề * VBA, loại bỏ các bản sao từ mảng *. Bạn làm cho một điểm tốt rằng mã của bạn không đi theo cách bạn sử dụng '.Count' mặc dù trong trường hợp này người hỏi có thể cần phải xác định nếu sự xuất hiện đầu tiên nên được giữ ở đầu hoặc botttom. – brettdj

0

Từ điển có một tối đa của 255 mặt hàng, vì vậy nếu bạn có nhiều giá trị mà bạn cần phải sử dụng một Bộ sưu tập. Thật không may, đối tượng Collection không có phương thức .Contains (a) hoặc .Exists (a), nhưng chức năng này xử lý (giả mạo) nó độc đáo bằng cách sử dụng các số lỗi:

CORRECTION: Từ điển không có giới hạn (nhờ Zairja). Tôi có thể đã sử dụng một số nguyên để lặp qua từ điển của tôi. Trong mọi trường hợp, chức năng này cho phép bạn kiểm tra bộ sưu tập cho sự tồn tại mục, vì vậy tôi sẽ để nó ở đây nếu nó hữu ích cho bất cứ ai:

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 

Vì vậy, nếu bạn cần một Bộ sưu tập, bạn có thể có khả năng chỉ cần thay thế

dict.Exists(strVal) 

với

CollContainsItem(coll, strVal) 

và thay thế

Set dict = CreateObject("Scripting.Dictionary") 

với

Set coll = CreateObject("Scripting.Collection") 

Và sử dụng còn lại của mã Zairja của. (Tôi đã không thực sự thử nó nhưng nó phải được đóng)

+2

Thực ra, đối tượng 'Dictionary' không giới hạn ở 255 mục. Đó chỉ là số lượng tối đa các mục mà trình gỡ rối hiển thị. Tôi tin rằng nó chỉ bị giới hạn bởi bộ nhớ (tôi đang sử dụng Excel 2010, nhưng trong phiên bản 2003 tôi có thể có từ điển với vài trăm nghìn phần tử). Ngoài ra, bạn muốn chắc chắn rằng nếu bạn đang sử dụng một số loại biến gia tăng, hãy chắc chắn rằng nó là 'Long' và không phải' Số nguyên' (sẽ dừng ở mức 256). – Zairja

+0

Ồ, số nguyên của Excel chỉ đến 256? Có lẽ đó là vấn đề của tôi tất cả cùng! –

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

Vui lòng không chỉnh sửa các câu trả lời của người dùng SO khác như bạn có trong [sửa đổi này] (http://stackoverflow.com/revisions/19693896/2) nếu có vấn đề với mã, nhận xét và cho họ biết. – Lankymart

+0

Bạn cần đặt dupBool thành false cho mỗi vòng lặp của i – 99moorem