TÍNH TỔNG NHIỀU ĐIỀU KIỆN TRONG VBA

Liên hệ QC

LamNA

Thành viên tích cực
Tham gia
3/6/14
Bài viết
897
Được thích
720
Giới tính
Nam
Nghề nghiệp
Quản Lý Cửa Hàng
Chào anh chị
Em thấy việc tính tổng nhiều điều kiện là công việc thường xuyên áp dụng cho rất nhiều người phục vụ cho việc báo cáo doanh thu, em cũng không ngoại lệ,
Em tìm bài viết trên diễn đàn cũng nhiều bạn quan tâm, vì thế mong anh chị xây dựng code VBA có thể giải quyết được bài toàn này một cách dễ hiểu nhất giống như hàm Sumifs nhưng không phải dạng dùng công thức trong VBA như các anh đã nói nó cũng như hàm không tăng tốc được tính toán.
Mong anh chị hỗ trợ để giúp ít cho nhiều thành viên trong diễn đàn, em cũng đang quan tâm vấn đề này
Em cám ơn
 
Vừa muốn tăng tốc, vừa giống sumifs thì khó đấy. Cái này nó kéo cái kia. :)
 
Upvote 0
Chào anh chị
Em thấy việc tính tổng nhiều điều kiện là công việc thường xuyên áp dụng cho rất nhiều người phục vụ cho việc báo cáo doanh thu, em cũng không ngoại lệ,
Em tìm bài viết trên diễn đàn cũng nhiều bạn quan tâm, vì thế mong anh chị xây dựng code VBA có thể giải quyết được bài toàn này một cách dễ hiểu nhất giống như hàm Sumifs nhưng không phải dạng dùng công thức trong VBA như các anh đã nói nó cũng như hàm không tăng tốc được tính toán.
Mong anh chị hỗ trợ để giúp ít cho nhiều thành viên trong diễn đàn, em cũng đang quan tâm vấn đề này
Em cám ơn
Lúc trước có viết cái tính SUM, MIN, MAX... 2 điều kiện. Bạn tham khảo file dưới đây rồi tùy biến theo ý mình nhé
 

File đính kèm

  • TransferData_5.xlsm
    1.4 MB · Đọc: 287
Upvote 0
Upvote 0
Chào anh chị
Em thấy việc tính tổng nhiều điều kiện là công việc thường xuyên áp dụng cho rất nhiều người phục vụ cho việc báo cáo doanh thu, em cũng không ngoại lệ,
Em tìm bài viết trên diễn đàn cũng nhiều bạn quan tâm, vì thế mong anh chị xây dựng code VBA có thể giải quyết được bài toàn này một cách dễ hiểu nhất giống như hàm Sumifs nhưng không phải dạng dùng công thức trong VBA như các anh đã nói nó cũng như hàm không tăng tốc được tính toán.
Mong anh chị hỗ trợ để giúp ít cho nhiều thành viên trong diễn đàn, em cũng đang quan tâm vấn đề này
Em cám ơn
Em bổ sung file mẫu để tiện thực hành xây dựng code
 

File đính kèm

  • TEST_TINHTONG_VBA.xlsm
    3.9 MB · Đọc: 171
Upvote 0
Chào anh chị
Em thấy việc tính tổng nhiều điều kiện là công việc thường xuyên áp dụng cho rất nhiều người phục vụ cho việc báo cáo doanh thu, em cũng không ngoại lệ,
Em tìm bài viết trên diễn đàn cũng nhiều bạn quan tâm, vì thế mong anh chị xây dựng code VBA có thể giải quyết được bài toàn này một cách dễ hiểu nhất giống như hàm Sumifs nhưng không phải dạng dùng công thức trong VBA như các anh đã nói nó cũng như hàm không tăng tốc được tính toán.
Mong anh chị hỗ trợ để giúp ít cho nhiều thành viên trong diễn đàn, em cũng đang quan tâm vấn đề này
Em cám ơn

Hai cái đỏ và xanh nó ít kjhi đi đôi với nhau.
Bạn phải chấp nhận rằng:
1. muốn tối ưu tốc đọ thì phải viết một hàm chuyên, chỉ dùng cho trường hợp đó, hoặc là
2. muốn mở rộng hàm để dễ sử dụng, dùng cho nhiều trường hợp thì hy sinh phần tốc độ.
Người viết code giỏi có cách để quân bình. Ngừoi viết code kinh nghiệm có cách để dò điểm mượt cho nhiều trường hợp.
(lưu ý màu xanh đỏ)
 
Upvote 0
Hai cái đỏ và xanh nó ít kjhi đi đôi với nhau.
Bạn phải chấp nhận rằng:
1. muốn tối ưu tốc đọ thì phải viết một hàm chuyên, chỉ dùng cho trường hợp đó, hoặc là
2. muốn mở rộng hàm để dễ sử dụng, dùng cho nhiều trường hợp thì hy sinh phần tốc độ.
Người viết code giỏi có cách để quân bình. Ngừoi viết code kinh nghiệm có cách để dò điểm mượt cho nhiều trường hợp.
(lưu ý màu xanh đỏ)
Em Cám ơn anh
Em chia sẻ 1 chút phần sumifs em đề cập đại khái code nó thân thiện giống như hàm sumifs để em hay các thành viên đang quan tâm nhìn code là biết áp dụng ngay về sau.
Em không biết diễn tả thể nào để hiểu được ý.
Kiểu cứ khai báo 1 mãng thì xét 1 cái điều kiện,... Đại khái là vậy đó anh.
Bài đã được tự động gộp:

Sao bài này bạn không dùng PivotTable?
Dữ liệu của bạn quá chuẩn, dùng PVT ngon quá rồi còn gì
Về pivot thì em áp dụng nó thường xuyên trong báo cáo rồi thầy, có điều định dạng hay cách dòng theo tùy ý thì hơi phiền phức.
 
Upvote 0
Về pivot thì em áp dụng nó thường xuyên trong báo cáo rồi thầy, có điều định dạng hay cách dòng theo tùy ý thì hơi phiền phức.
Vậy bạn định viết thành 1 function hay 1 sub?
Nếu viết thành function thì cuối cùng bạn vẫn phải gõ trên bảng tính. Vậy thôi gõ luôn SUMIFS cho rồi
Nếu viết thành Sub, e rằng mức độ tùy biến sẽ không cao
Nếu mục đích cuối cùng của bạn là viết 1 hàm giống như SUMIFS thì thôi... đừng. Tôi khuyên bạn không nên làm điều này bởi chúng ta không thắng được anh Bill về tốc độ đâu
Nếu mục đích của bạn là viết code tính tổng có điều kiện theo dữ liệu cụ thể nào đó thì có thể viết được với điều kiện chỉ áp dụng được với dữ liệu đó. Dữ liệu khác hơn sẽ không dùng được
Bạn tính sao?
 
Upvote 0
Vậy bạn định viết thành 1 function hay 1 sub?
Nếu viết thành function thì cuối cùng bạn vẫn phải gõ trên bảng tính. Vậy thôi gõ luôn SUMIFS cho rồi
Nếu viết thành Sub, e rằng mức độ tùy biến sẽ không cao
Nếu mục đích cuối cùng của bạn là viết 1 hàm giống như SUMIFS thì thôi... đừng. Tôi khuyên bạn không nên làm điều này bởi chúng ta không thắng được anh Bill về tốc độ đâu
Nếu mục đích của bạn là viết code tính tổng có điều kiện theo dữ liệu cụ thể nào đó thì có thể viết được với điều kiện chỉ áp dụng được với dữ liệu đó. Dữ liệu khác hơn sẽ không dùng được
Bạn tính sao?
Thầy viết một sub cho tham khảo nhe.
Em cám ơn
 
Upvote 0
Upvote 0
Cái bài 2 nó xóa trùng rồi tính tổng, còn em thì muốn xét những điều kiện cho trước
Ví dụ:
North
South
East
West
Nó cũng là 1 điều kiện để mình xét luôn đó thầy
Thì cũng vậy thôi mà. Tức là thêm điều kiện so sánh vào, ngoài ra code gần như y chang nhau
Viết đại cho bạn thế này:
Mã:
Sub SummaryData(ByVal Target As Range, ByVal Sum_Range As Range, _
               ByVal Criteria_Range1 As Range, Criteria1, _
               ByVal Criteria_Range2 As Range, Criteria2, _
               ByVal SummaryData1 As Range, ByVal SummaryData2 As Range)
  Dim aRes()
  Dim dic1 As Object
  Dim dic2 As Object
  Dim aCriteria1
  Dim aCriteria2
  Dim aSum
  Dim aData1
  Dim aData2
  Dim sData1
  Dim sData2
  Dim sCriteria1
  Dim sCriteria2
  Dim lRow As Long
  Dim lCol As Long
  Dim lRowCount As Long
  Dim idx As Long
  Dim p1 As Long, p2 As Long, ub As Long
  Dim dSum As Double
  On Error Resume Next

  Set dic1 = CreateObject("Scripting.Dictionary")
  Set dic2 = CreateObject("Scripting.Dictionary")

  aSum = Sum_Range.Value
  aCriteria1 = Criteria_Range1.Value
  aCriteria2 = Criteria_Range2.Value
  aData1 = SummaryData1.Value
  aData2 = SummaryData2.Value

  lRowCount = UBound(aData1, 1)
  ReDim aRes(1 To lRowCount, 1 To 1)
  ReDim tmpSum(1 To lRowCount, 1 To 1)
  ReDim tmpCount(1 To lRowCount, 1 To 1)
  lRow = 1: lCol = 1
  For idx = 1 To lRowCount
    If aData1(idx, 1) <> Empty Then
      If aData2(idx, 1) <> Empty Then
        sData1 = aData1(idx, 1)
        sData2 = aData2(idx, 1)
        sCriteria1 = aCriteria1(idx, 1)
        sCriteria2 = aCriteria2(idx, 1)
        dSum = CDbl(aSum(idx, 1))
        If sCriteria1 = Criteria1 Then
          If sCriteria2 = Criteria2 Then
            If Not dic1.Exists(sData1) Then
              lRow = lRow + 1
              dic1.Add sData1, lRow
              aRes(lRow, 1) = sData1
            End If
            If Not dic2.Exists(sData2) Then
              lCol = lCol + 1
              dic2.Add sData2, lCol
              ReDim Preserve aRes(1 To lRowCount, 1 To lCol)
              aRes(1, lCol) = sData2
            End If
            p1 = dic1.Item(sData1): p2 = dic2.Item(sData2)
            aRes(p1, p2) = CDbl(aRes(p1, p2)) + dSum
          End If
        End If
      End If
    End If
  Next
  Target.Resize(lRow, lCol).Value = aRes
End Sub
Sub Main()

  Dim wksSrc As Worksheet
  Dim wksDes As Worksheet
  Dim Target As Range
  Dim Sum_Range As Range
  Dim Criteria_Range1 As Range
  Dim Criteria_Range2 As Range
  Dim Criteria1
  Dim Criteria2
  Dim SummaryData1 As Range
  Dim SummaryData2 As Range

  Set wksSrc = Worksheets("Data")
  Set wksDes = Worksheets("Test2")
  Set Target = wksDes.Range("A4")
  Set Sum_Range = wksSrc.Range("G2:G100000")
  Set Criteria_Range1 = wksSrc.Range("E2:E100000")
  Set Criteria_Range2 = wksSrc.Range("D2:D100000")
  Criteria1 = wksDes.Range("G2").Value
  Criteria2 = wksDes.Range("F2").Value
  Set SummaryData1 = wksSrc.Range("A2:A100000")
  Set SummaryData2 = wksSrc.Range("C2:C100000")
  On Error Resume Next
  Target.CurrentRegion.ClearContents
  Application.ScreenUpdating = False
  SummaryData Target, Sum_Range, Criteria_Range1, Criteria1, Criteria_Range2, Criteria2, SummaryData1, SummaryData2
  With Target.CurrentRegion.Offset(, 1)
    .Sort .Rows(1), xlAscending, , , , , , , xlNo, , , xlLeftToRight
  End With
  Application.ScreenUpdating = True
End Sub
Bấm Alt + F8 chọn Sub Main để chạy code hoặc thay đổi cell F2, G2 thì sự kiện Change cũng sẽ chạy code
Ghi chú:
- SummaryData1 và SummaryData2 là 2 vùng cần tổng hợp (thành tiêu đề hàng và cột)
- Sum_Range là vùng tính tổng
- Criteria_Range1, Criteria_Range2 và 2 vùng điều kiện
- Criteria1, Criteria2 và 2 điều kiện
- Target là nơi đặt kết quả
Ở đây chỉ mới so sánh = dạng "thô sơ". Muốn giống SUMIF thì phải chơi được với ký tự đại diến "*", "?" hoặc so sánh >, >=, <, <= hoặc <> nữa (rắc rối lắm)
------------------------------------
Code này còn cả đống lỗi chưa bẫy. Bạn từ từ nghiên cứu đi
 

File đính kèm

  • TEST_TINHTONG_VBA.rar
    4.9 MB · Đọc: 227
Upvote 0
Thì cũng vậy thôi mà. Tức là thêm điều kiện so sánh vào, ngoài ra code gần như y chang nhau
Viết đại cho bạn thế này:
Mã:
Sub SummaryData(ByVal Target As Range, ByVal Sum_Range As Range, _
               ByVal Criteria_Range1 As Range, Criteria1, _
               ByVal Criteria_Range2 As Range, Criteria2, _
               ByVal SummaryData1 As Range, ByVal SummaryData2 As Range)
  Dim aRes()
  Dim dic1 As Object
  Dim dic2 As Object
  Dim aCriteria1
  Dim aCriteria2
  Dim aSum
  Dim aData1
  Dim aData2
  Dim sData1
  Dim sData2
  Dim sCriteria1
  Dim sCriteria2
  Dim lRow As Long
  Dim lCol As Long
  Dim lRowCount As Long
  Dim idx As Long
  Dim p1 As Long, p2 As Long, ub As Long
  Dim dSum As Double
  On Error Resume Next

  Set dic1 = CreateObject("Scripting.Dictionary")
  Set dic2 = CreateObject("Scripting.Dictionary")

  aSum = Sum_Range.Value
  aCriteria1 = Criteria_Range1.Value
  aCriteria2 = Criteria_Range2.Value
  aData1 = SummaryData1.Value
  aData2 = SummaryData2.Value

  lRowCount = UBound(aData1, 1)
  ReDim aRes(1 To lRowCount, 1 To 1)
  ReDim tmpSum(1 To lRowCount, 1 To 1)
  ReDim tmpCount(1 To lRowCount, 1 To 1)
  lRow = 1: lCol = 1
  For idx = 1 To lRowCount
    If aData1(idx, 1) <> Empty Then
      If aData2(idx, 1) <> Empty Then
        sData1 = aData1(idx, 1)
        sData2 = aData2(idx, 1)
        sCriteria1 = aCriteria1(idx, 1)
        sCriteria2 = aCriteria2(idx, 1)
        dSum = CDbl(aSum(idx, 1))
        If sCriteria1 = Criteria1 Then
          If sCriteria2 = Criteria2 Then
            If Not dic1.Exists(sData1) Then
              lRow = lRow + 1
              dic1.Add sData1, lRow
              aRes(lRow, 1) = sData1
            End If
            If Not dic2.Exists(sData2) Then
              lCol = lCol + 1
              dic2.Add sData2, lCol
              ReDim Preserve aRes(1 To lRowCount, 1 To lCol)
              aRes(1, lCol) = sData2
            End If
            p1 = dic1.Item(sData1): p2 = dic2.Item(sData2)
            aRes(p1, p2) = CDbl(aRes(p1, p2)) + dSum
          End If
        End If
      End If
    End If
  Next
  Target.Resize(lRow, lCol).Value = aRes
End Sub
Sub Main()

  Dim wksSrc As Worksheet
  Dim wksDes As Worksheet
  Dim Target As Range
  Dim Sum_Range As Range
  Dim Criteria_Range1 As Range
  Dim Criteria_Range2 As Range
  Dim Criteria1
  Dim Criteria2
  Dim SummaryData1 As Range
  Dim SummaryData2 As Range

  Set wksSrc = Worksheets("Data")
  Set wksDes = Worksheets("Test2")
  Set Target = wksDes.Range("A4")
  Set Sum_Range = wksSrc.Range("G2:G100000")
  Set Criteria_Range1 = wksSrc.Range("E2:E100000")
  Set Criteria_Range2 = wksSrc.Range("D2:D100000")
  Criteria1 = wksDes.Range("G2").Value
  Criteria2 = wksDes.Range("F2").Value
  Set SummaryData1 = wksSrc.Range("A2:A100000")
  Set SummaryData2 = wksSrc.Range("C2:C100000")
  On Error Resume Next
  Target.CurrentRegion.ClearContents
  Application.ScreenUpdating = False
  SummaryData Target, Sum_Range, Criteria_Range1, Criteria1, Criteria_Range2, Criteria2, SummaryData1, SummaryData2
  With Target.CurrentRegion.Offset(, 1)
    .Sort .Rows(1), xlAscending, , , , , , , xlNo, , , xlLeftToRight
  End With
  Application.ScreenUpdating = True
End Sub
Bấm Alt + F8 chọn Sub Main để chạy code hoặc thay đổi cell F2, G2 thì sự kiện Change cũng sẽ chạy code
Ghi chú:
- SummaryData1 và SummaryData2 là 2 vùng cần tổng hợp (thành tiêu đề hàng và cột)
- Sum_Range là vùng tính tổng
- Criteria_Range1, Criteria_Range2 và 2 vùng điều kiện
- Criteria1, Criteria2 và 2 điều kiện
- Target là nơi đặt kết quả
Ở đây chỉ mới so sánh = dạng "thô sơ". Muốn giống SUMIF thì phải chơi được với ký tự đại diến "*", "?" hoặc so sánh >, >=, <, <= hoặc <> nữa (rắc rối lắm)
------------------------------------
Code này còn cả đống lỗi chưa bẫy. Bạn từ từ nghiên cứu đi
Em cám ơn thầy nhe, do nhu cầu sát thực tế và giải thích từng dòng nhìn vào để dễ hiểu và áp dụng ngay nên thầy không rút gọn code cho ngắn.
Đó là lý do thành viên mới vào nghề nghiên cứu VBA nhìn code có sẵn đôi khi vài dòng lệnh mà không hiểu gì? Nhất là em haha
Cám ơn
Câu ngoài lề:
Thầy cho em đổi có kiểu định dạng ví dụ ngày 26/08/2018 ra kiểu Custom là quý không thầy?
 
Upvote 0
Hi Thầy!

Em xin thầy giúp em code làm sao tính tổng theo các điều kiện như File đính kèm
 

File đính kèm

  • Tong hop.xlsm
    31.6 KB · Đọc: 48
Upvote 0
Web KT
Back
Top Bottom