myhiep1811
Thành viên mới

- Tham gia
- 11/2/20
- Bài viết
- 1
- Được thích
- 0
dữ liệu lớn như thế này nên dung pivot table nhéEm chào anh/chị
Anh/ chị giúp em: em có một file excel dữ liệu trùng nhau rất nhiều lần. Em muốn lấy dữ liệu ngày gần nhất và xóa các dữ liệu trùng nhau.Thanks all
Sub GPE()
Application.ScreenUpdating = False
Dim sRng As Range, iArr As Variant, endR As Long
Sheet2.Range("A2:E1048576").ClearContents
With Sheet1
endR = .Range("A1048576").End(3).Row
.Range("A2:E" & endR).Sort Key1:=.Range("A1"), order1:=xlAscending, _
Key2:=.Range("E1"), order2:=xlDescending, _
Header:=xlYes
iArr = .Range("A2:E" & endR).Value
End With
Dim oArr As Variant, Dic As Object, iDic As Variant, I As Long, J As Long, R As Long
Set Dic = CreateObject("Scripting.Dictionary")
For I = LBound(iArr, 1) To UBound(iArr, 1)
If Not Dic.exists(CStr(iArr(I, 1))) Then Dic.Add CStr(iArr(I, 1)), I
Next
If Dic.Count = 0 Then
Application.ScreenUpdating = True
Exit Sub
End If
ReDim oArr(1 To Dic.Count, 1 To 5)
iDic = Dic.items
For I = LBound(iDic, 1) To UBound(iDic, 1)
R = iDic(I)
For J = 1 To 5
oArr(I + 1, J) = iArr(R, J)
Next
Next
Sheet2.Range("A2").Resize(UBound(oArr, 1), 5) = oArr
Application.ScreenUpdating = True
End Sub
Option Explicit
Sub Hic_HàNNôi_BanHànhCôngVan_GianCáchCovid_roi_BuonQuaaaaa_huhu()
Dim dic As Object, data(), rng As Range, i As Long, j As Long, k As Long
Set dic = CreateObject("Scripting.Dictionary")
With ThisWorkbook.Worksheets("Sheet1")
Set rng = .Cells(1, "A").CurrentRegion
rng.Sort Key1:=.Range("A1"), Order1:=xlAscending, Key2:=.Range("E1"), Order2:=xlDescending, Orientation:=xlTopToBottom, Header:=xlYes
End With
data = rng.Value
For i = 1 To UBound(data, 1)
If Not dic.Exists(data(i, 1)) Then
k = k + 1: dic.Add data(i, 1), k
For j = 1 To UBound(data, 2)
data(k, j) = data(i, j)
Next j
End If
Next i
With ThisWorkbook.Worksheets("KetQua").Cells(1, "A")
.CurrentRegion.ClearContents
If k Then .Resize(k, UBound(data, 2)).Value = data
End With
End Sub
Dữ liệu "nguyên xi" của người ta, đem đi Sort, nhìn lại "lạ hoắc" người ta có chịu không?Hic hic
Mã:Option Explicit Sub Hic_HàNNôi_BanHànhCôngVan_GianCáchCovid_roi_BuonQuaaaaa_huhu() Dim dic As Object, data(), rng As Range, i As Long, j As Long, k As Long Set dic = CreateObject("Scripting.Dictionary") With ThisWorkbook.Worksheets("Sheet1") Set rng = .Cells(1, "A").CurrentRegion rng.Sort Key1:=.Range("A1"), Order1:=xlAscending, Key2:=.Range("E1"), Order2:=xlAscending, Orientation:=xlTopToBottom, Header:=xlYes End With data = rng.Value For i = 1 To UBound(data, 1) If Not dic.Exists(data(i, 1)) Then k = k + 1: dic.Add data(i, 1), k For j = 1 To UBound(data, 2) data(k, j) = data(i, j) Next j End If Next i With ThisWorkbook.Worksheets("KetQua").Cells(1, "A") .CurrentRegion.ClearContents If k Then .Resize(k, UBound(data, 2)).Value = data End With End Sub
Option Explicit
Sub GPE()
Const CoLs As Long = 5
Dim Dic As Object, sArr(), dArr(), Txt As String
Dim I As Long, J As Long, K As Long, R As Long, Rws As Long
Set Dic = CreateObject("Scripting.Dictionary")
Dic.CompareMode = vbTextCompare
sArr = Sheet1.Range("A1", Sheet1.Range("A1").End(xlDown)).Resize(, CoLs).Value
R = UBound(sArr)
ReDim dArr(1 To R, 1 To CoLs)
For I = 1 To R
Txt = sArr(I, 1)
If Not Dic.Exists(Txt) Then
K = K + 1
Dic.Item(Txt) = K
For J = 1 To CoLs
dArr(K, J) = sArr(I, J)
Next J
Else
Rws = Dic.Item(Txt)
If sArr(I, CoLs) > dArr(Rws, CoLs) Then
dArr(Rws, 4) = sArr(I, 4)
dArr(Rws, CoLs) = sArr(I, CoLs)
End If
End If
Next I
With Sheets("KetQua")
.Range("A1:A100000").Resize(, CoLs).ClearContents
If K Then Range("A1").Resize(K, CoLs).Value = dArr
End With
Set Dic = Nothing
End Sub
Con chào Thầy, cảm ơn Thầy đã góp ý cho con ạ.Dữ liệu "nguyên xi" của người ta, đem đi Sort, nhìn lại "lạ hoắc" người ta có chịu không?
Đã xài Dic thì cứ cho nó lung tung cũng được mà.
PHP:Option Explicit Sub Hic_HàNNôi_BanHànhCôngVan_GianCáchCovid_roi_BuonQuaaaaa_huhu() Const CoLs As Long = 5 Dim Dic As Object, Data(), KQ(), i As Long, j As Long, k As Long, R As Long, Rws As Long Set Dic = CreateObject("Scripting.Dictionary") Data = Sheet1.Range("A2", Sheet1.Range("A2").End(xlDown)).Resize(, CoLs).Value Rws = UBound(Data) ReDim KQ(1 To Rws, 1 To CoLs) For i = 1 To Rws If Not Dic.Exists(Data(i, 1)) Then k = k + 1: Dic.Add Data(i, 1), k For j = 1 To CoLs KQ(k, j) = Data(i, j) Next j Else R = Dic.Item(Data(i, 1)) If Data(i, 5) > KQ(R, CoLs) Then KQ(R, 4) = Data(i, 4): KQ(R, CoLs) = Data(i, CoLs) End If End If Next i With Sheets("KetQua") .Range("A2:A100000").Resize(, CoLs).ClearContents If k Then Range("A2").Resize(k, CoLs).Value = Data End With End Sub
Chẳng hiểu sao code tôi sửa dựa theo bài của bạn ra kết quả "tào lao".Con chào Thầy, cảm ơn Thầy đã góp ý cho con ạ.
Dạ phải rồi Thầy ạ,sau khi gửi code lên con cũng có nghĩ thấy không ổn khi thay đổi dữ liệu gốc.
Data Model và Power Pivot chứ.dữ liệu lớn như thế này nên dung pivot table nhé
Cảm ơn Thầy , qua cách làm của Thầy con học thêm được chiêu so sánh ngày trong mảng mà không cần sử dụng tính năng sắp xếp.Chẳng hiểu sao code tôi sửa dựa theo bài của bạn ra kết quả "tào lao".
Đã gởi lại code ở bài trên.
-------------------------------
Đã thấy sai ở dòng này:
If k Then Range("A2").Resize(k, CoLs).Value = Data
Đúng phải là
If k Then Range("A2").Resize(k, CoLs).Value =KQ
Order2:=xlDescending
Dòng của bạn là dòng thứ tự (chỉ số) chứ không phải là dòng đếm. Tức là nó số ít chứ không phải số nhiều. Đặt tên không cần 's'....Dim I As Long, J As Long, K As Long, R As Long, Rws As Long
Theo góp ý của Thầy ,không động chạm đến dữ liệu ban đầu do vậy con thử dùng sort và bỏ Dic ạ:Dữ liệu "nguyên xi" của người ta, đem đi Sort, nhìn lại "lạ hoắc" người ta có chịu không?
Đã xài Dic thì cứ cho nó lung tung cũng được mà.
Public Sub TimGiaCuaNgayMoiNHat()
Dim Data(), Rng As Range, rKQ As Range, i As Long, j As Long, k As Long
With ThisWorkbook.Worksheets("Sheet1")
Set Rng = .Cells(1, "A").CurrentRegion
i = Rng.Columns.Count + 2
Rng.Offset(, i).Value = Rng.Value
Set rKQ = .Cells(1, "A").Offset(, i)
rKQ.CurrentRegion.Sort Key1:=rKQ, Order1:=xlAscending, Key2:=rKQ.Offset(, 4), Order2:=xlDescending, Orientation:=xlTopToBottom, Header:=xlYes
Data = rKQ.CurrentRegion.Value2: k = 1
For i = 2 To UBound(Data, 1)
If Data(i, 1) <> Data(i - 1, 1) Then
k = k + 1
For j = 1 To UBound(Data, 2)
Data(k, j) = Data(i, j)
Next j
End If
Next i
rKQ.Offset(1).Resize(Rng.Rows.Count - 1, Rng.Columns.Count).ClearContents
If k Then rKQ.Resize(k, UBound(Data, 2)).Value = Data
End With
End Sub
Vẫn sort dữ liệu gốc kìaTheo góp ý của Thầy ,không động chạm đến dữ liệu ban đầu do vậy con thử dùng sort và bỏ Dic ạ:
Ớ,cột A đến E thôi chú Mỹ nhéVẫn sort dữ liệu gốc kìa
Vẫn là sort. Sao chép, Sort, rồi xử lý, rồi xoá, rồi điền kết quả. current rồi Offset resize loằng ngoằng. Cứ bám vào 1 thuật toán ban đầu nó khổ vậy á. Đập hết làm lại còn hay hơnỚ,cột A đến E thôi chú Mỹ nhé
Con có thấy vấn đề gì đâu ạ.
Con cũng đang muốn đập đi xây cái "arraylist" , chú Mỹ xem thế nào giúp con ít vốn.Vẫn là sort. Sao chép, Sort, rồi xử lý, rồi xoá, rồi điền kết quả. current rồi Offset resize loằng ngoằng. Cứ bám vào 1 thuật toán ban đầu nó khổ vậy á. Đập hết làm lại còn hay hơn
Tôi còn chưa biết cái "arraylist" là kí rìCon cũng đang muốn đập đi xây cái "arraylist" , chú Mỹ xem thế nào giúp con ít vốn.![]()
Vậy là con hơn chú Mỹ món này rồi, con đã biết tham chiếu đến thư viên của nó và khai báoTôi còn chưa biết cái "arraylist" là kí rì
Sub GPE()
Const CoLs = 5
Dim iArr As Variant, endR As Long, oArr As Variant, Dic As Object, iDic As Variant
Dim I As Long, J As Long, K As Long, MS As String, idStr As String, R As Long
With Sheet1
endR = .Range("A1048576").End(3).Row
iArr = .Range("A2:E" & endR).Value
End With
Set Dic = CreateObject("Scripting.Dictionary")
For I = LBound(iArr, 1) To UBound(iArr, 1)
MS = CStr(iArr(I, 1))
If Not Dic.Exists(MS) Then
Dic.Add MS, I
Else
idStr = Dic.Item(MS)
If iArr(I, 4) > iArr(idStr, 4) Then
Dic.Remove MS
Dic.Add MS, I
End If
End If
Next
ReDim oArr(1 To Dic.Count, 1 To CoLs)
iDic = Dic.items
For I = LBound(iDic, 1) To UBound(iDic, 1)
R = iDic(I)
For J = 1 To CoLs
oArr(I + 1, J) = iArr(R, J)
Next
Next
With Sheet2
.Range("A2:E1048576").ClearContents
.Range("A2").Resize(UBound(oArr, 1), CoLs) = oArr
End With
End Sub
Cách của A Ba tê thì chỉ phải đi 1 vòng lặp qua dữ liệu gốc nên cho tốc độ nhanh hơn nhưng cái mảng dArr thực tế là thừa dòng so với kết quả thu được. Muốn ko khai thừa lại mất công đảo ngược mảng kết quả rồi redim preserve từng dòng 1 , đến cuối vẫn phải transpose . Tính ra thì vẫn phải đi mất 2 vòng lặp.If K Then Range("A1").Resize(K, CoLs).Value = dArr
Không có cách nào. Ngoài ra khai báo dArr dư cũng có lý do: Phải giả định rằng số dòng kết quả nhiều đến mức gần bằng hoặc bằng dữ liệu gốc. Dữ liệu khác thì có thể ước lượng, có khi ít hơn nhiều, cũng có khi nhiều hơn cả gốc.Có cách nào chỉ đi 1 vòng mà mảng kết quả có đúng số dòng cần lấy ko nhỉ?
Biết rồi thì làm đi.Vậy là con hơn chú Mỹ món này rồi, con đã biết tham chiếu đến thư viên của nó và khai báo![]()