Lọc dữ liệu trùng mảng 2 chiều dùng Dictionary
Nhờ mọi người giúp đỡ. Hiện tại mình đang dùng Dic để loại các dữ liệu trùng, bằng cách đếm ngược và check key tồn tại.
Tuy nhiên mình có 1 vấn đề là kích thước mảng trước và sau khi chạy code là khác nhau, nên khi mình xuất mảng kết quả thì bị chứa các giá trị <Empty>, mình có dùng Redim mảng kết quả trước khi gán dữ liệu nhưng cũng chưa ổn.Function ArrayRemoveDups(MyArray As Variant) As Variant Dim Vung As Variant Set Dic = CreateObject("scripting.dictionary") k = 0 ReDim Vung(1 To UBound(MyArray), 1 To UBound(MyArray, 2)) For i = 1 To UBound(MyArray) Gom = MyArray(i, 1) & "#" & MyArray(i, 2) & "#" & MyArray(i, 3) If Not Dic.exists(Gom) Then k = k + 1 Dic.Add Gom, i For j = 1 To UBound(MyArray, 2) Vung(k, j) = MyArray(i, j) Next j Debug.Print k End If Next i ReDim Temp(1 To Dic.Count, 1 To 3) Temp = Vung ArrayRemoveDups = Temp End FunctionĐang ngâm cứu cái "ReDim Preserve" của anh ndu96081631 mà vẫn chưa thấm.
www.giaiphapexcel.com/diendan/threads/nh%E1%BB%9D-h%C6%B0%E1%BB%9Bng-d%E1%BA%ABn-s%E1%BB%AD-d%E1%BB%A5ng-dictionary-object.42791/post-280564www.giaiphapexcel.com/diendan/threads/th%E1%BA%AFc-m%E1%BA%AFc-v%E1%BB%81-h%C3%A0m-udf-uniquelist.53572/post-338184
Add thêm dữ liệu cho dễ hình dung.
Option Explicit
Function ArrayRemoveDups(MyArray As Variant) As Variant
const sdeli = "#"
Dim Vung As Variant
Dim i as long, k as long, dic as object, res as variant, Gom as string, j as long, Vung as variant
Dim ub1 as long, ub2 as long
ub1 = ubound(MyArray,1)
ub2= ubound(MyArray , 2)
Set Dic = CreateObject("scripting.dictionary")
k = 0
ReDim Vung(1 To UBound(MyArray), 1 To UBound(MyArray, 2))
For i = 1 To ub1
Gom = MyArray(i, 1) & sdeli & MyArray(i, 2) & sdeli & MyArray(i, 3)
If Not Dic.exists(Gom) Then
k = k + 1
Dic.Add Gom, ""
For j = 1 To ub2
Vung(k, j) = MyArray(i, j)
Next j
' Debug.Print k'
End If
Next i
if k>0 then
redim res(1 to 2)
res(1) = Vung
res(2) = k
ArrayRemoveDups = res
end if
End Function
'——*************————-'
Áp dụng:
Dim ketqua as varaint, data as variant, dulieu as variant
'data = …
ketqua = ArrayRemoveDups(data)
If isarray(ketqua)= true then
dulieu = ketqua(1)
Sheet1.range("A1").resize(ketqua(2), ubound(dulieu,2)).value=dulieu
End if
www.giaiphapexcel.com/diendan/threads/l%E1%BB%8Dc-d%E1%BB%AF-li%E1%BB%87u-tr%C3%B9ng-m%E1%BA%A3ng-2-chi%E1%BB%81u-d%C3%B9ng-dictionary.151680/
Khóa học Power PI – Ứng dung trong Nhân sự
TỔNG QUAN KHÓA HỌC: POWER BI CHO NGÀNH NHÂN SỰ Khóa học Power BI cho Nhân sự được thiết kế dành riêng cho các...
Xem khóa học
ban thử:
Thử
Sao không viết cho tổng quát luôn? Chẳng lẽ mảng nguồn của bạn luôn có 3 cột à? Cũng có nghĩa đối với vùng dữ liệu 1 cột, 2 cột thì không áp dụng được hàm?
Nguyên tắc lọc duy nhất mảng 2 chiều dùng dic:
– Dùng vòng lập đưa key bạn cần vào dic và đánh dấu vị trí (trong Items)
– Từ vị trí đã có trong items, lấy dữ liệu xuống mảng kết quả
– Vậy ta có ít nhất 2 vòng lập (không tính vòng lập đi ngang qua các cột)
Tóm lại là giống bài 11 và phát triển ra thêm.
Lưu ý rằng với mảng 2 chiều bạn không thể dùng ReDim Preserve cho chiều thứ nhất đâu nha
Bạn còn phải tính đến trường hợp có dòng rổng ở giữa vùng dữ liệu nữa nhé
Lúc đó thì:
iKey sẽ = "###" và vẫn được nạp vào dic
1 cell thì isEmpty chứ 3 cells gộp lại, có dấu"#" phân cách ở giữa thì nó hết Empty rồi bạn à
Code tổng quát lọc duy nhất theo vị trí cột tùy ý:
Ghi chú:
– SourceArray: Nguồn dữ liệu, có thể là vùng dữ liệu trên sheet, cũng có thể là mảng nằm ở đâu đó trên listbox, combobox hoặc mảng do công thức trả về
– Columns: Là những cột mà bạn muốn lấy duy nhất. Nó có thể là một hoặc nhiều cột. Nếu bỏ qua tham số này hoặc ghi là "*" thì xem như là lọc duy nhất toàn bộ các cột
– Hàm này không lấy dòng rổng, không lấy dòng có cell bị lỗi
Cách dùng:
Code trên lọc duy nhất vùng dữ liệu O6:Q1000 theo cột 1 và cột 2, đặt kết quả tại cell K6
———————————————————-
Cũng không chắc còn lỗi nào không? Mời bạn kiểm tra giúp
Thử lệnh
a = RemoveDups(, Array(1, 3))
bị lổi
Tùy quan điểm mỗi người, theo mình nên lấy dòng tô vàng trong file
Đúng là tôi chưa tính tới cái lỗi cố tình này
Đã định On Error Resume Next lên đầu code rồi nhưng thôi, cứ để vậy, còn lỗi nào mình sẽ giải quyết tận gốc luôn
—————————————-
Bạn cho ví dụ cụ thể xem, tôi chưa hiểu lắm
Vâng! Tôi cũng suy nghĩ lại rồi, đúng là không thể rào hết toàn bộ các lỗi, nhất là những lỗi cố tình. Ngay cả các hàm của MS cũng vậy, nếu ta cố tình làm cho đối số của hàm vượt ra khỏi giới hạn thì nó cũng phải báo lỗi thôi. Ví dụ:
vùng dữ liệu có 3 cột mà đòi tìm ở cột 4 thì.. thua, chỉ có nước báo #REF! mà thôi
Vậy nên tôi quyết định giải quyết ý kiến ở [URL='giaiphapexcel.com/diendan/threads/l%E1%BB%8Dc-d%E1%BB%AF-li%E1%BB%87u-tr%C3%B9ng-m%E1%BA%A3ng-2-chi%E1%BB%81u-d%C3%B9ng-dictionary.151680/post-989226']bài 23 theo cách:
Đại khái vậy
Code của thầy ndu96081631, Tôi chuẩn hóa lại giúp bạn để tiện dụng hơn. Bạn có thể tham khảo thêm ADODB để xử lý dữ liệu lớn.
Bạn có thể vận dụng đa dạng như sau:
1. RemoveDups(rng, Array(1, 2,4))
2. RemoveDups(rng, "1,2,18")
3. RemoveDups(rng, "O,Q,S")
4. RemoveDups(rng, "B,O:Q")
5. RemoveDups(rng, )
6. RemoveDups(rng, "*")
7. RemoveDups(rng, "")
Thêm hai tham số tùy chọn, phân biệt hoa thường với ký tự, và cắt chuỗi rỗng đầu cuối chuỗi.
RemoveDups(rng, "", TRUE,TRUE)
—————-
Nhắc mới nhớ nha
Lúc đầu viết code tôi có nghĩ tới, xong loay hoay lát tự dưng quên luôn. Cảm ơn bạn
—————————–
Nghe đồn rằng ADO chỉ làm việc được với dữ liệu nhỏ hơn 65536 dòng, điều đó có đúng không?
Có thể em hiểu sai ý của các anh.
Em đang để dữ liệu tại ô A1 và A100000
Dùng ADODB.Recordset lấy dữ liệu và paste qua Sheet"Data_XuLy". Vẫn dùng ngon lành.
Nếu đã đánh dấu vị trí trong Dic thì sao không tận dụng Index để gán kết quả. Đặt Key theo cách của mình thì có thể lấy luôn ô trống và ô bị lỗi. Mọi người test thử nhé.