Bạn thử code này xem:Kính nhờ Anh/chị giúp em xóa dữ liệu trùng lặp và đánh số thứ tự tự động sau mỗi lần xóa dữ liệu trùng lặp. (theo file đính kèm)
em trân trọng cảm ơn Anh/chị.
Option Explicit
Sub RemoveDuplicate()
Dim sArr(), dArr(), Dic As Object, I As Long, J As Long, sU1 As Long
With Sheets("Data")
sArr = .Range("B4: C" & .Cells(.Rows.Count, "B").End(xlUp).Row).Value
sU1 = UBound(sArr, 1)
ReDim dArr(1 To sU1, 1 To 5)
Set Dic = CreateObject("Scripting.Dictionary")
For I = sU1 To 1 Step -1
If Not Dic.exists(sArr(I, 2)) Then
J = J + 1
Dic.Add sArr(I, 2), ""
dArr(J, 1) = J
dArr(J, 4) = sArr(I, 1)
dArr(J, 5) = sArr(I, 2)
End If
Next
For I = 1 To J
dArr(I, 2) = dArr(J, 4)
dArr(I, 3) = dArr(J, 5)
J = J - 1
Next
.Range("K4").Resize(10000, 3).ClearContents
.Range("K4").Resize(Dic.Count, 3) = dArr
End With
Set Dic = Nothing
End Sub
Viết vậy phải đảm bảo dữ liệu đã sắp xếp theo ngày tháng.RemoveDuplicate
For I = sU1 To 1 Step -1
Cái này hợp lý nè anhỞ vòng lặp đầu bạn gán key = nội dung cột C, item = (ngày tháng cột B, chỉ số)
Nếu key đã tồn tại thì đối chiếu ngày, nếu ngày lớn hơn thì ghi mới vào mảng kết quả.
anh oi lam on xem lại giúp em, hay anh chạy luôn vào file em mô tả, vì em mới học nên copy nó ko chạy. em cảm ơnBạn thử code này xem:
Mã:Option Explicit Sub RemoveDuplicate() Dim sArr(), dArr(), Dic As Object, I As Long, J As Long, sU1 As Long With Sheets("Data") sArr = .Range("B4: C" & .Cells(.Rows.Count, "B").End(xlUp).Row).Value sU1 = UBound(sArr, 1) ReDim dArr(1 To sU1, 1 To 5) Set Dic = CreateObject("Scripting.Dictionary") For I = sU1 To 1 Step -1 If Not Dic.exists(sArr(I, 2)) Then J = J + 1 Dic.Add sArr(I, 2), "" dArr(J, 1) = J dArr(J, 4) = sArr(I, 1) dArr(J, 5) = sArr(I, 2) End If Next For I = 1 To J dArr(I, 2) = dArr(J, 4) dArr(I, 3) = dArr(J, 5) J = J - 1 Next .Range("K4").Resize(10000, 3).ClearContents .Range("K4").Resize(Dic.Count, 3) = dArr End With Set Dic = Nothing End Sub
Option Explicit
Sub xoadulieu()
Dim Lr&, i&
Lr = Cells(Rows.Count, "C").End(xlUp).Row
With CreateObject("Scripting.dictionary")
For i = Lr To 4 Step -1
If Not .exists(Cells(i, "C").Value) Then
.Add Cells(i, "C").Value, Cells(i, "B").Value
End If
Next
Range("A4:C" & Lr).Clear
For i = .Count To 1 Step -1
Cells(i + 3, "A").Value = i
Cells(i + 3, "B").Value = .items()(.Count - i)
Cells(i + 3, "C").Value = .keys()(.Count - i)
Next
End With
End Sub
đại ca bebo021999 xem lại giúp em, khi chạy nó bị mất tiêu đề cột ạDùng thử cái này. Kết quả sẽ đè lên dữ liệu gốc theo yêu cầu của bạn (không biết có phải yêu cầu là thế không?).
PHP:Option Explicit Sub xoadulieu() Dim Lr&, i& Lr = Cells(Rows.Count, "C").End(xlUp).Row With CreateObject("Scripting.dictionary") For i = Lr To 4 Step -1 If Not .exists(Cells(i, "C").Value) Then .Add Cells(i, "C").Value, Cells(i, "B").Value End If Next Range("A4:C" & Lr).Clear For i = .Count To 1 Step -1 Cells(i + 3, "A").Value = i Cells(i + 3, "B").Value = .items()(.Count - i) Cells(i + 3, "C").Value = .keys()(.Count - i) Next End With End Sub
Tại sao không lấy kết quả luôn khi duyệt dic.Mà lại phải thêm 1 vòng lặp nữa.Dùng thử cái này. Kết quả sẽ đè lên dữ liệu gốc theo yêu cầu của bạn (không biết có phải yêu cầu là thế không?).
PHP:Option Explicit Sub xoadulieu() Dim Lr&, i& Lr = Cells(Rows.Count, "C").End(xlUp).Row With CreateObject("Scripting.dictionary") For i = Lr To 4 Step -1 If Not .exists(Cells(i, "C").Value) Then .Add Cells(i, "C").Value, Cells(i, "B").Value End If Next Range("A4:C" & Lr).Clear For i = .Count To 1 Step -1 Cells(i + 3, "A").Value = i Cells(i + 3, "B").Value = .items()(.Count - i) Cells(i + 3, "C").Value = .keys()(.Count - i) Next End With End Sub
Theo file ví dụ thì dữ liệu bắt đầu từ dòng 4.đại ca bebo021999 xem lại giúp em, khi chạy nó bị mất tiêu đề cột ạ
Câu này nghe quen quen, hỏi mấy lần rồi đúng không. Phải duyệt dic xong hết mới có KQ để so sánh chứ.Tại sao không lấy kết quả luôn khi duyệt dic.Mà lại phải thêm 1 vòng lặp nữa.
Em cũng đang ngồi chờ xem. Đang chưa nảy số được là ghi như nào. Chờ xem học hỏi được gì không nè anhCâu này nghe quen quen, hỏi mấy lần rồi đúng không. Phải duyệt dic xong hết mới có KQ để so sánh chứ
Option Explicit
Sub abc()
Dim i
With CreateObject("Scripting.Dictionary")
For i = Sheet4.Range("A" & Rows.Count).End(xlUp).Row To 4 Step -1
If .exists(Sheet4.Range("C" & i).Value) = 0 Then
.Item(Sheet4.Range("C" & i).Value) = ""
Else
Sheet4.Rows(i).EntireRow.Delete
End If
Next i
End With
Sheet4.Range("A4", Sheet4.Range("A4").End(xlDown)).Formula = "=row()-3"
End Sub
Vòng lặp đầu tiên là duyệt dic, dữ liệu ban đầu có 7 dòng nên biến i phải chạy từ 1 tới 7. Ở đây lấy giá trị cuối nên i chạy từ 11 tới 4.Tại sao không lấy kết quả luôn khi duyệt dic.Mà lại phải thêm 1 vòng lặp nữa.
Cái này mà nhiều dòng dữ liệu nó có bị quay đắm đuối không anh nhỉ@duy_quang Tham khảo thêm 1 cách dùng cho file bài 1
Mã:Option Explicit Sub abc() Dim i With CreateObject("Scripting.Dictionary") For i = Sheet4.Range("A" & Rows.Count).End(xlUp).Row To 4 Step -1 If .exists(Sheet4.Range("C" & i).Value) = 0 Then .Item(Sheet4.Range("C" & i).Value) = "" Else Sheet4.Rows(i).EntireRow.Delete End If Next i End With Sheet4.Range("A4", Sheet4.Range("A4").End(xlDown)).Formula = "=row()-3" End Sub
Sub ABC()
Dim sArr(), Dic As Object, i&, j&, K&, Res(), Key
Set Dic = CreateObject("scripting.dictionary")
Application.ScreenUpdating = False
With Sheets("data")
sArr = .Range("A4:C" & .Range("B" & Rows.Count).End(3).Row).Value
ReDim Res(1 To UBound(sArr, 1), 1 To 3)
For i = UBound(sArr, 1) To 1 Step -1
If Dic.exists(UCase(sArr(i, 3))) = False Then
Dic.Item(UCase(sArr(i, 3))) = i
End If
Next
For Each Key In Dic.keys
K = K + 1
Res(K, 2) = sArr(Dic.Item(Key), 2)
Res(K, 3) = sArr(Dic.Item(Key), 3)
Next
.Range("A4:C1000").ClearContents
.Range("A4").Resize(K, 3).Value = Res
.Range("A4").Resize(K, 3).Sort .Range("B3"), xlAscending
.Range("A4").Value = 1
.Range("A4").AutoFill .Range("A4").Resize(K), xlFillSeries
End With
Application.ScreenUpdating = True
End Sub
Thử viết lại chỉ 1 vòng For iThử 1 cách khácMã:Sub ABC() Dim sArr(), Dic As Object, i&, j&, K&, Res(), Key Set Dic = CreateObject("scripting.dictionary") Application.ScreenUpdating = False With Sheets("data") sArr = .Range("A4:C" & .Range("B" & Rows.Count).End(3).Row).Value ReDim Res(1 To UBound(sArr, 1), 1 To 3) For i = UBound(sArr, 1) To 1 Step -1 If Dic.exists(UCase(sArr(i, 3))) = False Then Dic.Item(UCase(sArr(i, 3))) = i End If Next For Each Key In Dic.keys K = K + 1 Res(K, 2) = sArr(Dic.Item(Key), 2) Res(K, 3) = sArr(Dic.Item(Key), 3) Next .Range("A4:C1000").ClearContents .Range("A4").Resize(K, 3).Value = Res .Range("A4").Resize(K, 3).Sort .Range("B3"), xlAscending .Range("A4").Value = 1 .Range("A4").AutoFill .Range("A4").Resize(K), xlFillSeries End With Application.ScreenUpdating = True End Sub
Thấy bạn @snow25 có ý tưởng hay nên học đòi viết thử vậy thôi ban. File mẫu dữ liệu cũng ít mà đầu bài lại không thấy nói "dữ liệu hàng vài trăm ngàn dòng" nên mới viết như vậy.Cái này mà nhiều dòng dữ liệu nó có bị quay đắm đuối không anh nhỉ
Dạ, để em viết ạ!Thử viết lại chỉ 1 vòng For i
Sub RemoveDuplicate()
Dim sArr, Dic As Object, I As Long, k As Long, vitri As Long
Set Dic = CreateObject("Scripting.Dictionary")
With Sheets("Data")
sArr = .Range("A4: C" & .Cells(.Rows.Count, "B").End(xlUp).Row).Value
For I = 1 To UBound(sArr)
If Not Dic.exists(sArr(I, 3)) Then
k = k + 1
Dic.Add sArr(I, 3), k
sArr(k, 1) = k
sArr(k, 2) = sArr(I, 2)
sArr(k, 3) = sArr(I, 3)
Else
vitri = Dic.Item(sArr(I, 3))
If sArr(vitri, 2) < sArr(I, 2) Then sArr(vitri, 2) = sArr(I, 2)
End If
Next
.Range("K4").Resize(10000, 3).ClearContents
.Range("K4").Resize(k, 3) = sArr
End With
Set Dic = Nothing
End Sub
Hiện thực hóa ý tưởng anh @befaint và viết vào file cho bạn luôn nhé:anh oi lam on xem lại giúp em, hay anh chạy luôn vào file em mô tả, vì em mới học nên copy nó ko chạy. em cảm ơn
Option Explicit
Sub RemoveDuplicate()
Dim sArr(), dArr(), Dic As Object, I As Long, J As Long, X, sU1 As Long
With Sheets("Data")
sArr = .Range("B4: C" & .Cells(.Rows.Count, "B").End(xlUp).Row).Value
sU1 = UBound(sArr, 1)
ReDim dArr(1 To sU1, 1 To 3)
Set Dic = CreateObject("Scripting.Dictionary")
For I = 1 To sU1
If Not Dic.exists(sArr(I, 2)) Then
J = J + 1
Dic.Add sArr(I, 2), Array(sArr(I, 1), J)
dArr(J, 1) = J
dArr(J, 2) = sArr(I, 1)
dArr(J, 3) = sArr(I, 2)
Else
X = Dic.Item(sArr(I, 2))
If sArr(I, 1) > X(0) Then
dArr(X(1), 2) = sArr(I, 1)
End If
End If
Next
.Range("G4").Resize(10000, 3).ClearContents
.Range("G4").Resize(Dic.Count, 3) = dArr
End With
Set Dic = Nothing
End Sub