Dạng bài này có trên GPE lâu rồiBài này thường ngày tôi làm bằng Pivot table, nay tôi muốn học thêm VBA nhờ các bác làm giúp.
Xin cảm ơn rất nhiều
Xem file này, tôi vận dụng code của NDU.Chà chà file này nặng quá, máy của tôi sau khi mở chọn hàm max để tính, không hiểu sao 3 phút rồi mà chưa xong.
Bạn thử file mới này xem thế nào nhéChà chà file này nặng quá, máy của tôi sau khi mở chọn hàm max để tính, không hiểu sao 3 phút rồi mà chưa xong.
Qua bài transferData_5 của NDU mới thấy lợi hại của việc khai báo số dòng và cột của mảng. Khai dư quá thì chậm hơn khai vừa đủ và nếu cần thì dùng redim.Bạn thử file mới này xem thế nào nhé
Code đã được cải tiến thêm rất nhiều. Máy tôi cho ra kết quả trong vòng 0.7 giây với dữ liệu 65000 dòng
Tôi thấy trên diễn đàn, có bài toán bao gồm 2 Sub trở lên, thường có 2 phương án:
- Từng Sub trên một Module (Module1, Module 2...)
- Gộp chung các Sub vào trong 1 Module
Xin hỏi trong 2 cách trên thì cách nào thuận tiện hơn.
Sub TaoBC()
Dim endR&, i&, iR&, iC&, nR&, nC&
Dim Arr, ArrKQ
Dim Tmp01$, Tmp02$
Dim Dic01 As Object, Dic02 As Object
Set Dic01 = CreateObject("Scripting.Dictionary")
Set Dic02 = CreateObject("Scripting.Dictionary")
With Sheets("Data")
.AutoFilterMode = False
endR = .Cells(65000, 1).End(3).Row
Arr = .Range(.Cells(2, 1), .Cells(endR, 3)).Value
End With
ReDim ArrKQ(1 To UBound(Arr), 1 To 200)
iR = 1: iC = 1
For i = 1 To UBound(Arr)
If Len(CStr(Arr(i, 1))) > 0 Then
If Len(CStr(Arr(i, 2))) > 0 Then
Tmp01 = CStr(Arr(i, 1))
If Not Dic01.Exists(Tmp01) Then
iR = iR + 1
Dic01.Add Tmp01, iR
ArrKQ(iR, 1) = Tmp01
End If
Tmp02 = Arr(i, 2)
If Not Dic02.Exists(Tmp02) Then
iC = iC + 1
Dic02.Add Tmp02, iC
ArrKQ(1, iC) = Tmp02
End If
nR = Dic01.Item(Tmp01)
nC = Dic02.Item(Tmp02)
ArrKQ(nR, nC) = ArrKQ(nR, nC) + Arr(i, 3)
End If
End If
Next i
If iR And iC Then
With Sheets("sheet2")
.Cells.ClearContents
.[A1].Resize(iR, iC) = ArrKQ
End With
End If
Erase Arr, ArrKQ
Set Dic01 = Nothing: Set Dic02 = Nothing
End Sub
Bạn muốn đặt sao tùy thích. Riêng tôi, nếu chỉ có 2 Sub thì chẳng việc gì chia ra 2 moduleTôi thấy trên diễn đàn, có bài toán bao gồm 2 Sub trở lên, thường có 2 phương án:
- Từng Sub trên một Module (Module1, Module 2...)
- Gộp chung các Sub vào trong 1 Module
Xin hỏi trong 2 cách trên thì cách nào thuận tiện hơn.
- Vòng lập duyệt từ trên xuốngBài toán này trông thế mà phức tạp gớm
Những dòng khai báo trên thì không vấn đề gì, nhưng đến công thức mấu chốt nhất của bài thì phức tạp đây (hình dung mãi nhưng chưa hiểu lắm)
ArrKQ(nR, nC) = ArrKQ(nR, nC) + Arr(i, 3)
Nhờ các pác giải thích dùm công thức trên, cho tôi hình dung cụ thể khi sau khi i chạy đến 12 (tức chạy đến Ô A13) thì ArrKQ(nR,nC)=Arr(2,2) chăng ?
(nR và iR hình như là một tức nR=ỉR? nhưng hình như không phải)
Nhờ các pác giải thích dùm công thức trên, cho tôi hình dung cụ thể khi sau khi i chạy đến 12 (tức chạy đến Ô A13) thì ArrKQ(nR,nC)=Arr(2,2) chăng ? (nR và iR hình như là một tức nR=ỉR? nhưng hình như không phải)
Vì code của bác ấy có dùng thuộc tính End(xlUP), mục đích xác định dòng cuối cùng có dữ liệu... Và cái thằng End(xlUP) này sẽ bị sai khi sheet đang có AutoFilterBác Thu Nghi giải thích giúp
With Sheets("Data")
.AutoFilterMode = False
có tác dụng gì thế? Tại sao cần dùng đến nó hả bác
Theo kinh nghiệm tối ưu hóa code thì việc so sánh số lượng kí tự trong chuỗi sẽ nhanh hơn là so sánh trực tiếp chuỗi đó, tức là nếu bạn so sánh giữa Len(a)=0 và a="" thì Len(a)=0 sẽ nhanh hơn.Xin thày Ndu giải thích hộ đoạn If Len(CStr(Arr(i, 1))) > 0 Then tại sao không dùng là If Arr(i, 1) <> "" Then vừa đơn giản, máy đỡ phải chuyển đổi >> nhanh hơn.
Sub Tonghop()
Dim DL(), eR As Long, i As Long, j As Long, Tmp1, Tmp2, Dong, Cot
With Sheets("Sheet1")
eR = .[C65000].End(xlUp).Row
DL = .Range("A2:C" & eR).Value
ReDim KQ(1 To UBound(DL, 1) + 1, 1 To UBound(DL, 1) + 1)
Set Dic1 = CreateObject("Scripting.Dictionary")
Set Dic2 = CreateObject("Scripting.Dictionary")
n = 1
m = 1
For i = 1 To UBound(DL, 1)
If DL(i, 1) <> "" Then
Tmp1 = DL(i, 1)
If Not Dic1.Exists(Tmp1) Then
n = n + 1
Dic1.Add Tmp1, n
Dong = Dic1.Item(Tmp1)
KQ(n, 1) = Tmp1
If DL(i, 2) <> "" Then
Tmp2 = DL(i, 2)
If Not Dic2.Exists(Tmp2) Then
m = m + 1
Dic2.Add Tmp2, m
Cot = Dic2.Item(Tmp2)
KQ(1, m) = Tmp2
KQ(Dong, Cot) = KQ(Dong, Cot) + DL(i, 3)
End If
End If
End If
End If
Next
End With
With Sheets("Sheet2")
.Cells.ClearContents
.[A1].Resize(Dong, Cot).Value = KQ
End With
End Sub
Sai quá trời luôn!Do chưa có kinh nghiệm, sau khi viết Code khi chạy vẫn ra kết quả nhưng tổng hợp không đúng, phiền mọi người xem hộ tôi, chỉ tôi nhầm ở đâu.
PHP:Sub Tonghop() Dim DL(), eR As Long, i As Long, j As Long, Tmp1, Tmp2, Dong, Cot With Sheets("Sheet1") eR = .[C65000].End(xlUp).Row DL = .Range("A2:C" & eR).Value ReDim KQ(1 To UBound(DL, 1) + 1, 1 To UBound(DL, 1) + 1) Set Dic1 = CreateObject("Scripting.Dictionary") Set Dic2 = CreateObject("Scripting.Dictionary") n = 1 m = 1 For i = 1 To UBound(DL, 1) If DL(i, 1) <> "" Then Tmp1 = DL(i, 1) If Not Dic1.Exists(Tmp1) Then n = n + 1 Dic1.Add Tmp1, n Dong = Dic1.Item(Tmp1) KQ(n, 1) = Tmp1 If DL(i, 2) <> "" Then Tmp2 = DL(i, 2) If Not Dic2.Exists(Tmp2) Then m = m + 1 Dic2.Add Tmp2, m Cot = Dic2.Item(Tmp2) KQ(1, m) = Tmp2 KQ(Dong, Cot) = KQ(Dong, Cot) + DL(i, 3) End If End If End If End If Next End With With Sheets("Sheet2") .Cells.ClearContents .[A1].Resize(Dong, Cot).Value = KQ End With End Sub
Sub Tonghop()
Dim DL, eR As Long, i As Long, n As Long, m As Long, Tmp1, Tmp2, Dong, Cot
Dim Dic1 As Object, Dic2 As Object, KQ()
With Sheets("Sheet1")
DL = .Range(.[A2], .[C65000].End(xlUp)).Value
End With
ReDim KQ(1 To UBound(DL, 1), 1 To UBound(DL, 1))
Set Dic1 = CreateObject("Scripting.Dictionary")
Set Dic2 = CreateObject("Scripting.Dictionary")
n = 1
m = 1
For i = 1 To UBound(DL, 1)
If DL(i, 1) <> "" And DL(i, 2) <> "" Then
Tmp1 = DL(i, 1)
If Not Dic1.Exists(Tmp1) Then
n = n + 1
Dic1.Add Tmp1, n
KQ(n, 1) = Tmp1
End If
Tmp2 = DL(i, 2)
If Not Dic2.Exists(Tmp2) Then
m = m + 1
Dic2.Add Tmp2, m
KQ(1, m) = Tmp2
End If
Dong = Dic1.Item(Tmp1)
Cot = Dic2.Item(Tmp2)
KQ(Dong, Cot) = KQ(Dong, Cot) + DL(i, 3)
End If
Next
With Sheets("Sheet2")
.Cells.ClearContents
.[A1].Resize(Dong, Cot).Value = KQ
End With
End Sub