tanthanh94
Thành viên mới
- Tham gia
- 24/8/14
- Bài viết
- 46
- Được thích
- 3
Hiện tại file sử dụng hàm sumif rất nhiều dòng
Nay nhờ các Anh viết code để giảm dung lượng file
Public Sub GPE()
Dim Dic As Object, sArr(), dArr(), I As Long, Tem As String
Set Dic = CreateObject("Scripting.Dictionary")
sArr = Range([B5], [B5].End(xlDown)).Resize(, 5).Value2
ReDim dArr(1 To UBound(sArr, 1), 1 To 1)
For I = 1 To UBound(sArr, 1)
Tem = sArr(I, 1)
If Not Dic.Exists(Tem) Then
Dic.Add Tem, sArr(I, 5)
Else
Dic.Item(Tem) = Dic.Item(Tem) + sArr(I, 5)
End If
Next I
For I = 1 To UBound(sArr, 1)
dArr(I, 1) = Dic.Item(sArr(I, 1))
Next I
[H5].Resize(I - 1) = dArr
Set Dic = Nothing
End Sub
Do file của em có 13 sheet dùng công thức như vậy nên cần code để giảm dung lượng fileSUMIF với 5000 dòng chưa phải là "oải".
Muốn Sub thì tặng bạn cái này.
PHP:Public Sub GPE() Dim Dic As Object, sArr(), dArr(), I As Long, Tem As String Set Dic = CreateObject("Scripting.Dictionary") sArr = Range([B5], [B5].End(xlDown)).Resize(, 5).Value2 ReDim dArr(1 To UBound(sArr, 1), 1 To 1) For I = 1 To UBound(sArr, 1) Tem = sArr(I, 1) If Not Dic.Exists(Tem) Then Dic.Add Tem, sArr(I, 5) Else Dic.Item(Tem) = Dic.Item(Tem) + sArr(I, 5) End If Next I For I = 1 To UBound(sArr, 1) dArr(I, 1) = Dic.Item(sArr(I, 1)) Next I [H5].Resize(I - 1) = dArr Set Dic = Nothing End Sub
SUMIF với 5000 dòng chưa phải là "oải".
Muốn Sub thì tặng bạn cái này.
PHP:Public Sub GPE() Dim Dic As Object, sArr(), dArr(), I As Long, Tem As String Set Dic = CreateObject("Scripting.Dictionary") sArr = Range([B5], [B5].End(xlDown)).Resize(, 5).Value2 ReDim dArr(1 To UBound(sArr, 1), 1 To 1) For I = 1 To UBound(sArr, 1) Tem = sArr(I, 1) If Not Dic.Exists(Tem) Then Dic.Add Tem, sArr(I, 5) Else Dic.Item(Tem) = Dic.Item(Tem) + sArr(I, 5) End If Next I For I = 1 To UBound(sArr, 1) dArr(I, 1) = Dic.Item(sArr(I, 1)) Next I [H5].Resize(I - 1) = dArr Set Dic = Nothing End Sub
Application.WorksheetFunction.SumIf
Cải thiện hơn đó bạn, khi đó ngoài sheet chỉ là các số CHẾT, ko phải là công thức nên Excel ko tính toán khi có sự thay đổi nữa.Xin hỏi em dùngtrong VBA có cải thiện tốt hơn khi dùng công thức ngoài sheets khôngPHP:Application.WorksheetFunction.SumIf
Sau khi chạy code xong, việc cải thiện nó nằm ở chỗ: Trên bảng tính không còn công thức nữa ---> Không còn gì để tính toán nữa ---> Dẫn đến bảng tính sẽ nhanhXin hỏi em dùngtrong VBA có cải thiện tốt hơn khi dùng công thức ngoài sheets khôngPHP:Application.WorksheetFunction.SumIf
SUMIF với 5000 dòng chưa phải là "oải".
Muốn Sub thì tặng bạn cái này.
PHP:Public Sub GPE() Dim Dic As Object, sArr(), dArr(), I As Long, Tem As String Set Dic = CreateObject("Scripting.Dictionary") sArr = Range([B5], [B5].End(xlDown)).Resize(, 5).Value2 ReDim dArr(1 To UBound(sArr, 1), 1 To 1) For I = 1 To UBound(sArr, 1) Tem = sArr(I, 1) If Not Dic.Exists(Tem) Then Dic.Add Tem, sArr(I, 5) Else Dic.Item(Tem) = Dic.Item(Tem) + sArr(I, 5) End If Next I For I = 1 To UBound(sArr, 1) dArr(I, 1) = Dic.Item(sArr(I, 1)) Next I [H5].Resize(I - 1) = dArr Set Dic = Nothing End Sub
Bên trên khai báo "Tem as String"Anh Ba Tê ơi, sao tôi chạy thử code của anh và thay dữ liệu A, B C... thành ngày /tháng/ năm thì nó chỉ ra giá trị 0 nhỉ. Bài toán của tôi là cộng tự động các giá trị nếu cùng ngày. Ví dụ ngày 20/11/2017 cùng phát sinh 200 và dòng khác 20/11/2017 phát sinh giá trị 300 thì giá trị tổng cộng phải là 500. Tôi thử khai báo sArr và dArr là kiểu date nhưng không được. Chân thành cảm ơn anh.
Bên trên khai báo "Tem as String"
Bạn chỉ cần thay bằng "Tem as Variant" hoặc bỏ "as String" là được.
1/ Code chạy từ B5 xuống tới khi kết thúc dữ liệu cuối cùng, giống như kiểu bạn nhấn Ctrl+ Down, nếu từ B5 trờ xuống k có dữ liệu thì nó sẽ chạy tới ô cuối trong sheet cho nên kết quả sẽ trả về giống như bạn thấy.Cảm ơn a Ba Tê rất nhiều ạ, tuy nhiên tôi lại gặp phải 1 trường hợp oái ăm và có thêm 3 câu hỏi, mong anh chỉ giáo cho người mới tìm hiểu VBA như tôi:
1. Khi bỏ "as string" hoặc khai báo thành Variant như anh thì gặp lỗi: "khi tôi xóa hết dữ liệu ở cột B thì chạy code nó tự cộng tổng thành giá trị 2380 tất cả các dòng từ H5 đến dòng cuối cùng của cột H".
2. Nếu bây giờ bài toán của tôi phát sinh thêm việc: tôi muốn VBA tự động lookup những số liệu có ngày tháng mà sau khi tính tổng như sumif ở cột H thì đưa lên tương ứng ngày tháng có đã ghi sẵn hàng ngang ở hàng 2 (Điền vào hàng 3 hoặc hàng tương ứng bất kỳ dưới hàng 2 có mã tên giống mã tên cột H)thì sẽ viết code như thế nào anh nhỉ?
3: Nếu tại ô B2 tôi điền tay là 1 ngày bất kỳ thì từ ô C2 đến ô CZX2 tự động điền các ngày tiếp theo liên tiếp với ngày đã điền, sau đó lookup giá trị đã được sumif ở cột H tương ứng với ngày trên hàng 3 (tính từ ô B3). Mục hỏi 2 và 3 tôi đã làm đc công tác này bằng công thức hàm nhưng file có 30 sheet dữ liệu thì rất nặng nên muốn dùng VBA cho nhẹ hơn.
4: Nếu tôi thay ngược lại cột F (từ F5) là ngày tháng, cột B (Từ B5) là khối lượng thì phải viết code đổi lại thế nào để vẫn tính được?
Trân trọng cảm ơn phản hồi của a Ba Tê và các anh chị khác góp ý. (Vui lòng xem file đính kèm)
Bạn thử.Mình đang đau đầu với code VBA để thay thế hàm sumif. Dử liệu chứa vùng điều kiện và vùng cần tính tổng lấy từ Sheets("BK_NX") > kết quả có chứa điều kiện mình cần trên Sheets("M_SAP").
>>> Bạn nào có code hay cho mình tham khảo với nhé
Sub tinhtong()
Dim arr, i As Long, j As Long, lr As Long, dic As Object, dk As String, a As Long, kq() As Double, lr1 As Long
Set dic = CreateObject("scripting.dictionary")
With Sheets("M_sap")
lr = .Range("B" & Rows.Count).End(xlUp).Row
If lr < 5 Then Exit Sub
arr = .Range("B5:C" & lr).Value
ReDim kq(1 To UBound(arr), 1 To 3)
For i = 1 To UBound(arr)
dk = arr(i, 1)
dic.Item(dk) = i
Next i
End With
With Sheets("bk_nx")
lr1 = .Range("H" & Rows.Count).End(xlUp).Row
arr = .Range("H6:K" & lr1).Value
For i = 1 To UBound(arr)
dk = arr(i, 1)
a = dic.Item(dk)
If a Then
kq(a, 1) = kq(a, 1) + arr(i, 3)
kq(a, 2) = kq(a, 2) + arr(i, 4)
kq(a, 3) = kq(a, 1) - kq(a, 2)
End If
Next i
End With
With Sheets("M_sap")
.Range("E5:G" & lr).Value = kq
End With
End Sub
Thật tuyệt vời. Cảm ơn Bạn nhiều nhiều nhé.Bạn thử.
Mã:Sub tinhtong() Dim arr, i As Long, j As Long, lr As Long, dic As Object, dk As String, a As Long, kq() As Double, lr1 As Long Set dic = CreateObject("scripting.dictionary") With Sheets("M_sap") lr = .Range("B" & Rows.Count).End(xlUp).Row If lr < 5 Then Exit Sub arr = .Range("B5:C" & lr).Value ReDim kq(1 To UBound(arr), 1 To 3) For i = 1 To UBound(arr) dk = arr(i, 1) dic.Item(dk) = i Next i End With With Sheets("bk_nx") lr1 = .Range("H" & Rows.Count).End(xlUp).Row arr = .Range("H6:K" & lr1).Value For i = 1 To UBound(arr) dk = arr(i, 1) a = dic.Item(dk) If a Then kq(a, 1) = kq(a, 1) + arr(i, 3) kq(a, 2) = kq(a, 2) + arr(i, 4) kq(a, 3) = kq(a, 1) - kq(a, 2) End If Next i End With With Sheets("M_sap") .Range("E5:G" & lr).Value = kq End With End Sub
Mình không rành về VBA nên lên đây nhờ các bạn giúp đỡ về code thay thế hàm sumifs. Mình có gửi File đính kèm, trong File mình đang dùng công thức. Chân thành cảm ơn các bạn!
Cho mình hỏi nếu bài này mà chỉ muốn điền kết quả vào dòng đầu tiên của điều kiện thì sửa lại như nào (kiểu như trong ảnh)SUMIF với 5000 dòng chưa phải là "oải".
Muốn Sub thì tặng bạn cái này.
PHP:Public Sub GPE() Dim Dic As Object, sArr(), dArr(), I As Long, Tem As String Set Dic = CreateObject("Scripting.Dictionary") sArr = Range([B5], [B5].End(xlDown)).Resize(, 5).Value2 ReDim dArr(1 To UBound(sArr, 1), 1 To 1) For I = 1 To UBound(sArr, 1) Tem = sArr(I, 1) If Not Dic.Exists(Tem) Then Dic.Add Tem, sArr(I, 5) Else Dic.Item(Tem) = Dic.Item(Tem) + sArr(I, 5) End If Next I For I = 1 To UBound(sArr, 1) dArr(I, 1) = Dic.Item(sArr(I, 1)) Next I [H5].Resize(I - 1) = dArr Set Dic = Nothing End Sub
Bạn đưa file "giống thật" lên đi, rồi nêu rõ yêu cầu, vài dòng kết quả mẫu.Cho mình hỏi nếu bài này mà chỉ muốn điền kết quả vào dòng đầu tiên của điều kiện thì sửa lại như nào (kiểu như trong ảnh)
View attachment 237172
Sub Sum_data_manual()
Dim SumArr(), Sarr()
Dim i As Long, j As Long, l As Long, SLBan As Double, SLTralai As Double, TongBan As Double
Dim SumLr As Long, SumLcol As Long, SLr As Long, SLcol As Long, TG As Double, TongTraLai As Double
TG = Timer()
Application.Calculation = xlCalculationManual
Application.ScreenUpdating = False
SumLr = Sheet1.Range("F" & Rows.Count).End(xlUp).Row
SumLcol = Sheet1.Cells(11, Columns.Count).End(xlToLeft).Column
SumArr = Sheet1.Range("A8").Resize(SumLr - 8 + 1, SumLcol - 1 + 1) ' tu A8
SLr = Sheet2.Range("A" & Rows.Count).End(xlUp).Row
SLcol = Sheet2.Cells(8, Columns.Count).End(xlToLeft).Column
Sarr = Sheet2.Range("A8").Resize(SLr - 8 + 1, SLcol - 1 + 1) ' tu A8
For i = 5 To UBound(SumArr, 1)
If SumArr(i, 1) = Empty And SumArr(i, 6) <> "" Then
For j = UBound(SumArr, 2) To 17 Step -3
For l = 2 To UBound(Sarr, 1)
If SumArr(i, 6) = Sarr(l, 5) And SumArr(1, j) = Sarr(l, 3) Then
If SumArr(4, j) = "3=1-2" Then
SLTralai = SumArr(i, j - 1) + Sarr(l, 16)
SumArr(i, j - 1) = Round(SLTralai, 2)
SLBan = SumArr(i, j - 2) + Sarr(l, 7)
SumArr(i, j - 2) = Round(SLBan, 2)
SumArr(i, j) = Round(SLBan - SLTralai, 2)
SLBan = 0: SLTralai = 0
End If
End If
Next l
Next j
End If
Next i
Sheet1.Range("A8").Resize(SumLr - 8 + 1, SumLcol - 1 + 1) = SumArr
Application.Calculation = xlCalculationAutomatic
Application.ScreenUpdating = True
MsgBox "Done " & Round(Timer() - TG, 2)
End Sub