Code VBA tính tổng từ 2 bảng khác nhau thành 1 bảng

Liên hệ QC

moihocvba

Thành viên thường trực
Tham gia
16/8/20
Bài viết
211
Được thích
50
Chào anh chị GPE, anh chị giúp em viết một code VBA lấy giá trị tên hàng và không trùng từ CỬA HÀNG 1 VÀ CỬA HÀNG 2 sau đó cộng số lượng đó lại cho ra kết quả là bảng TỔNG 2 CỬA HÀNG giúp em với!
Tổng hợp từ 1 bảng thì em dùng dictionary đc, nhưng kết hợp 2 bảng tự nhiên em bị rối.
Em cảm ơn anh chị nhiều ạ!

1621217710296.png
 

File đính kèm

  • Loc Trung.xlsm
    9.7 KB · Đọc: 20
Chào anh chị GPE, anh chị giúp em viết một code VBA lấy giá trị tên hàng và không trùng từ CỬA HÀNG 1 VÀ CỬA HÀNG 2 sau đó cộng số lượng đó lại cho ra kết quả là bảng TỔNG 2 CỬA HÀNG giúp em với!
Tổng hợp từ 1 bảng thì em dùng dictionary đc, nhưng kết hợp 2 bảng tự nhiên em bị rối.
Em cảm ơn anh chị nhiều ạ!

View attachment 258788
Có gì đâu mà rối. Cứ khai báo 2 mảng nguồn, hoặc nhiều hơn tùy thích. Duyệt qua tất cả các mảng đó và nạp vào Dic. Nếu chưa có thì nạp vào, nếu có thì cộng thêm vào
Cuối cùng gán kết quả xuống sheet thôi
 
Upvote 0
Có gì đâu mà rối. Cứ khai báo 2 mảng nguồn, hoặc nhiều hơn tùy thích. Duyệt qua tất cả các mảng đó và nạp vào Dic. Nếu chưa có thì nạp vào, nếu có thì cộng thêm vào
Cuối cùng gán kết quả xuống sheet thôi
Dạ em cảm ơn anh Quang_Hải, em biết là làm vậy, nhưng ko biết viết code sao, cái chỗ dictionary đó em vẫn chưa hiểu lắm nên làm kiểu rập khuôn như mấy anh chị đã chỉ, qua bài này thì em ko còn biết áp dụng sao cho đúng. Mong anh chỉ giáo!

"Duyệt qua tất cả các mảng đó và nạp vào Dic" em chưa biết làm chỗ này nè anh, nên một mảng thì làm được, nhiều hơn thì em chưa biết.
 
Upvote 0
Dạ em cảm ơn anh Quang_Hải, em biết là làm vậy, nhưng ko biết viết code sao, cái chỗ dictionary đó em vẫn chưa hiểu lắm nên làm kiểu rập khuôn như mấy anh chị đã chỉ, qua bài này thì em ko còn biết áp dụng sao cho đúng. Mong anh chỉ giáo!

"Duyệt qua tất cả các mảng đó và nạp vào Dic" em chưa biết làm chỗ này nè anh, nên một mảng thì làm được, nhiều hơn thì em chưa biết.
Đại khái như thế này. Tùy theo dữ liệu thật mình sẽ viết khác nhau và có thể gọn hơn nhưng phức tạp hơn
Code kiểu này dài dòng nhưng đơn giản dễ hiểu
Mã:
Sub Tong_Hop()
Dim sArr1(), sArr2(), Dic As Object, i As Long, k As Long, Res(), tmp As String
Set Dic = CreateObject("scripting.dictionary")
With Sheets("sheet1")
   sArr1 = .Range("A3", .Range("A" & Rows.Count).End(3)).Resize(, 2).Value
   sArr2 = .Range("D3", .Range("D" & Rows.Count).End(3)).Resize(, 2).Value
End With
ReDim Res(1 To (UBound(sArr1) + UBound(sArr2)), 1 To 2)
For i = 1 To UBound(sArr1)
   tmp = LCase(sArr1(i, 1))
   If Not Dic.exists(tmp) Then
      k = k + 1
      Dic.Add tmp, k
      Res(k, 1) = sArr1(i, 1)
      Res(k, 2) = sArr1(i, 2)
   Else
      Res(Dic.Item(tmp), 2) = Res(Dic.Item(tmp), 2) + sArr1(i, 2)
   End If
Next
For i = 1 To UBound(sArr2)
   tmp = LCase(sArr2(i, 1))
   If Not Dic.exists(tmp) Then
      k = k + 1
      Dic.Add tmp, k
      Res(k, 1) = sArr2(i, 1)
      Res(k, 2) = sArr2(i, 2)
   Else
      Res(Dic.Item(tmp), 2) = Res(Dic.Item(tmp), 2) + sArr1(i, 2)
   End If
Next
Sheets("sheet1").Range("G3").Resize(k, 2) = Res
End Sub
 
Upvote 0
Đại khái như thế này. Tùy theo dữ liệu thật mình sẽ viết khác nhau và có thể gọn hơn nhưng phức tạp hơn
Code kiểu này dài dòng nhưng đơn giản dễ hiểu
Mã:
Sub Tong_Hop()
Dim sArr1(), sArr2(), Dic As Object, i As Long, k As Long, Res(), tmp As String
Set Dic = CreateObject("scripting.dictionary")
With Sheets("sheet1")
   sArr1 = .Range("A3", .Range("A" & Rows.Count).End(3)).Resize(, 2).Value
   sArr2 = .Range("D3", .Range("D" & Rows.Count).End(3)).Resize(, 2).Value
End With
ReDim Res(1 To (UBound(sArr1) + UBound(sArr2)), 1 To 2)
For i = 1 To UBound(sArr1)
   tmp = LCase(sArr1(i, 1))
   If Not Dic.exists(tmp) Then
      k = k + 1
      Dic.Add tmp, k
      Res(k, 1) = sArr1(i, 1)
      Res(k, 2) = sArr1(i, 2)
   Else
      Res(Dic.Item(tmp), 2) = Res(Dic.Item(tmp), 2) + sArr1(i, 2)
   End If
Next
For i = 1 To UBound(sArr2)
   tmp = LCase(sArr2(i, 1))
   If Not Dic.exists(tmp) Then
      k = k + 1
      Dic.Add tmp, k
      Res(k, 1) = sArr2(i, 1)
      Res(k, 2) = sArr2(i, 2)
   Else
      Res(Dic.Item(tmp), 2) = Res(Dic.Item(tmp), 2) + sArr1(i, 2)
   End If
Next
Sheets("sheet1").Range("G3").Resize(k, 2) = Res
End Sub
Dạ em hiểu rồi anh, cám ơn anh rất nhiều vì sự hỗ trợ! Để em áp dụng vào file của em.
 
Upvote 0
Dạ em hiểu rồi anh, cám ơn anh rất nhiều vì sự hỗ trợ! Để em áp dụng vào file của em.
Tặng bạn kiểu viết phức tạp "mảng trong mảng". Rảnh thì nghiên cứu cho biết thêm
Mã:
Sub Tong_Hop_ArrayInArray()
Dim sArr1(), sArr2(), Dic As Object, i As Long, k As Long, Res(), tmp As String, sArr(), n As Long, x As Long
Set Dic = CreateObject("scripting.dictionary")
With Sheets("sheet1")
   sArr1 = .Range("A3", .Range("A" & Rows.Count).End(3)).Resize(, 2).Value
   sArr2 = .Range("D3", .Range("D" & Rows.Count).End(3)).Resize(, 2).Value
End With
sArr = Array(sArr1, sArr2)
ReDim Res(1 To (UBound(sArr1) + UBound(sArr2)), 1 To 2)
For n = LBound(sArr) To UBound(sArr)
   For i = 1 To UBound(sArr(n))
      tmp = LCase(sArr(n)(i, 1))
      If Not Dic.exists(tmp) Then
         k = k + 1
         Dic.Add tmp, k
         Res(k, 1) = sArr(n)(i, 1)
         Res(k, 2) = sArr(n)(i, 2)
      Else
         x = Dic.Item(tmp)
         Res(x, 2) = Res(x, 2) + sArr(n)(i, 2)
      End If
   Next
Next
Sheets("sheet1").Range("G3").Resize(k, 2) = Res
End Sub
 
Upvote 0
Tặng bạn kiểu viết phức tạp "mảng trong mảng". Rảnh thì nghiên cứu cho biết thêm
Mã:
Sub Tong_Hop_ArrayInArray()
Dim sArr1(), sArr2(), Dic As Object, i As Long, k As Long, Res(), tmp As String, sArr(), n As Long, x As Long
Set Dic = CreateObject("scripting.dictionary")
With Sheets("sheet1")
   sArr1 = .Range("A3", .Range("A" & Rows.Count).End(3)).Resize(, 2).Value
   sArr2 = .Range("D3", .Range("D" & Rows.Count).End(3)).Resize(, 2).Value
End With
sArr = Array(sArr1, sArr2)
ReDim Res(1 To (UBound(sArr1) + UBound(sArr2)), 1 To 2)
For n = LBound(sArr) To UBound(sArr)
   For i = 1 To UBound(sArr(n))
      tmp = LCase(sArr(n)(i, 1))
      If Not Dic.exists(tmp) Then
         k = k + 1
         Dic.Add tmp, k
         Res(k, 1) = sArr(n)(i, 1)
         Res(k, 2) = sArr(n)(i, 2)
      Else
         x = Dic.Item(tmp)
         Res(x, 2) = Res(x, 2) + sArr(n)(i, 2)
      End If
   Next
Next
Sheets("sheet1").Range("G3").Resize(k, 2) = Res
End Sub
Cám ơn anh!
Mấu chốt vấn đề là ở dòng này phải ko anh "sArr = Array(sArr1, sArr2)"
Em hiểu là dòng này kết hợp nhiều mảng thành một mảng sArr, sau đó thao tác xử lý giống như một mảng bình thường. Em thấy cách thứ 2 này của anh code gọn mà dễ hiểu hơn anh!

Ví dụ như có thêm mảng sArr3 nữa thì mình cũng kết hợp kiểu: "sArr = Array(sArr1, sArr2, sArr3)" như vầy đúng ko anh? vậy thì mình cũng dùng nhiều vòng lặp như cách 1, quá hay!
 
Upvote 0
Cám ơn anh!
Mấu chốt vấn đề là ở dòng này phải ko anh "sArr = Array(sArr1, sArr2)"
Em hiểu là dòng này kết hợp nhiều mảng thành một mảng sArr, sau đó thao tác xử lý giống như một mảng bình thường. Em thấy cách thứ 2 này của anh code gọn mà dễ hiểu hơn anh!

Ví dụ như có thêm mảng sArr3 nữa thì mình cũng kết hợp kiểu: "sArr = Array(sArr1, sArr2, sArr3)" như vầy đúng ko anh? vậy thì mình cũng dùng nhiều vòng lặp như cách 1, quá hay!
Cứ thêm vào và chạy thử, xem kết quả như thế nào. Mình cũng đã và đang tự học bằng cách thử. Thử không mất phí mà

Vì file bạn đính kèm chỉ là dữ liệu tạm nên code tạm như vậy, nếu có dữ liệu thật thì cách viết sẽ khác, có thể sẽ phức tạp hơn hoặc đơn giản hơn.

Nhìn chung bạn đã hiểu cách mình dùng mảng mẹ và mảng con để rút gọn code. Bạn rất thông minh đó.
 
Upvote 0
Chào anh chị GPE, anh chị giúp em viết một code VBA lấy giá trị tên hàng và không trùng từ CỬA HÀNG 1 VÀ CỬA HÀNG 2 sau đó cộng số lượng đó lại cho ra kết quả là bảng TỔNG 2 CỬA HÀNG giúp em với!
Tổng hợp từ 1 bảng thì em dùng dictionary đc, nhưng kết hợp 2 bảng tự nhiên em bị rối.
Em cảm ơn anh chị nhiều ạ!

View attachment 258788
Dữ liệu nguồn đâu có Xoài đâu bạn? Từ Bưởi biến thành Xoài???

1621224733152.png
 
Upvote 0
Được khuyến mại xoài, nhưng mất bưởi. Tôi nghĩ có thể đổi Bưởi để lấy Xoài???
Ấy chết con nhầm chú ơi, tại ghi dữ liệu tạm nên con bị nhầm lẫn. Lần sau con sẽ chú ý hơn. Cám ơn chú nhiều!
Anh Quang_Hải đã giúp con áp dụng thành công vào file con rồi ạ!
Cám ơn mọi người!
 
Upvote 0
Ấy chết con nhầm chú ơi, tại ghi dữ liệu tạm nên con bị nhầm lẫn. Lần sau con sẽ chú ý hơn. Cám ơn chú nhiều!
Anh Quang_Hải đã giúp con áp dụng thành công vào file con rồi ạ!
Cám ơn mọi người!
Thêm cho bạn 1 cách khác để tham khảo.

Mã:
Sub GopDL_HLMT()
    Dim cnn As String
    cnn = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & ThisWorkbook.FullName & ";Extended Properties=""Excel 12.0 Xml;HDR=No"""
    With CreateObject("ADODB.Recordset")
        .Open ("Select F1,Sum(F2) From (Select * From [Sheet1$A3:B] Union All Select * From [Sheet1$D3:E]) Group By F1"), cnn
        Sheet1.Range("J3").CopyFromRecordset .DataSource
    End With
End Sub
 
Upvote 0
Thêm cho bạn 1 cách khác để tham khảo.

Mã:
Sub GopDL_HLMT()
    Dim cnn As String
    cnn = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & ThisWorkbook.FullName & ";Extended Properties=""Excel 12.0 Xml;HDR=No"""
    With CreateObject("ADODB.Recordset")
        .Open ("Select F1,Sum(F2) From (Select * From [Sheet1$A3:B] Union All Select * From [Sheet1$D3:E]) Group By F1"), cnn
        Sheet1.Range("J3").CopyFromRecordset .DataSource
    End With
End Sub
Dạ con cám ơn chú nhiều! Nhiều lần con tập tành AODB nhưng có lẽ trình con chưa tới nên con chưa thẩm thấu được chú, con sẽ để dành code của chú nghiên cứu!
 
Upvote 0
Trên bình diện bài nảy. Chả có lý do gì buộc phải dùng hai mảng cả.
Cứ dùng một mảng vài lần cũng chả chết ai.
 
Upvote 0
Thêm cho bạn 1 cách khác để tham khảo.

Mã:
Sub GopDL_HLMT()
    Dim cnn As String
    cnn = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & ThisWorkbook.FullName & ";Extended Properties=""Excel 12.0 Xml;HDR=No"""
    With CreateObject("ADODB.Recordset")
        .Open ("Select F1,Sum(F2) From (Select * From [Sheet1$A3:B] Union All Select * From [Sheet1$D3:E]) Group By F1"), cnn
        Sheet1.Range("J3").CopyFromRecordset .DataSource
    End With
End Sub
Cực kỳ nhanh và hiệu quả!
 
Upvote 0
Trong bài trên, tôi viết là "một mảng". Ý tôi là chưa chắc cần đến mảng Res gì gì đó.

' code làm công việc của Consolidate
For each rgCol In Array("A", "D")
a = .Range(.Cells(3, rgCol), .Cells(.Rows.Count, rgCol).End(3)).Resize(, 2).Value
For i = 1 To UBound(a)
Dic(a(i, 1)) = Dic.(a(i, 1)) + a(i, 2)
Next i
Next rgCol
.Range("J3").Resize(Dic.Count,).Value = Appliucation.Transpose(Dic.Keys())
.Range("K3").Resize(Dic.Count,).Value = Appliucation.Transpose(Dic.Items())
 
Upvote 0
Trên bình diện bài nảy. Chả có lý do gì buộc phải dùng hai mảng cả.
Cứ dùng một mảng vài lần cũng chả chết ai.
Cho em hỏi anh VetMini là nếu so sánh việc mình dùng 1 mảng lặp lại nhiều lần vs dùng nhiều mảng thì ngoài việc ko phải khai báo nhiều biến thì nó có ảnh hưởng tới tốc độ xử lý ko anh? Em mới học nên hơi gà ạ!
 
Upvote 0
Tôi không trả lời những câu hỏi có từ viết tắt. Trừ phi những từ ấy là từ kỹ thuật, đã thành từ ngữ chung.
 
Upvote 0
Đại khái như thế này. Tùy theo dữ liệu thật mình sẽ viết khác nhau và có thể gọn hơn nhưng phức tạp hơn
Code kiểu này dài dòng nhưng đơn giản dễ hiểu
Mã:
Sub Tong_Hop()
Dim sArr1(), sArr2(), Dic As Object, i As Long, k As Long, Res(), tmp As String
Set Dic = CreateObject("scripting.dictionary")
With Sheets("sheet1")
   sArr1 = .Range("A3", .Range("A" & Rows.Count).End(3)).Resize(, 2).Value
   sArr2 = .Range("D3", .Range("D" & Rows.Count).End(3)).Resize(, 2).Value
End With
ReDim Res(1 To (UBound(sArr1) + UBound(sArr2)), 1 To 2)
For i = 1 To UBound(sArr1)
   tmp = LCase(sArr1(i, 1))
   If Not Dic.exists(tmp) Then
      k = k + 1
      Dic.Add tmp, k
      Res(k, 1) = sArr1(i, 1)
      Res(k, 2) = sArr1(i, 2)
   Else
      Res(Dic.Item(tmp), 2) = Res(Dic.Item(tmp), 2) + sArr1(i, 2)
   End If
Next
For i = 1 To UBound(sArr2)
   tmp = LCase(sArr2(i, 1))
   If Not Dic.exists(tmp) Then
      k = k + 1
      Dic.Add tmp, k
      Res(k, 1) = sArr2(i, 1)
      Res(k, 2) = sArr2(i, 2)
   Else
      Res(Dic.Item(tmp), 2) = Res(Dic.Item(tmp), 2) + sArr1(i, 2)
   End If
Next
Sheets("sheet1").Range("G3").Resize(k, 2) = Res
End Sub
em chào bác ạ!
bác có thể giúp em gộp dữ liệu theo file này không ạ. em không rành về VBA nên không biết làm thế nào để sửa lại code cho phù hợp.
Em cần gộp dữ liệu từ 2 mảng nhưng dữ liệu số lượng lại tính tổng riêng cho từng mảng. chứ không tính tổng chung cả hai mảng. mong bác giúp đỡ ạ!
 

File đính kèm

  • GOPDL.xlsm
    11.4 KB · Đọc: 8
Upvote 0
em chào bác ạ!
bác có thể giúp em gộp dữ liệu theo file này không ạ. em không rành về VBA nên không biết làm thế nào để sửa lại code cho phù hợp.
Em cần gộp dữ liệu từ 2 mảng nhưng dữ liệu số lượng lại tính tổng riêng cho từng mảng. chứ không tính tổng chung cả hai mảng. mong bác giúp đỡ ạ!
Bạn copy code này về sử dụng và sửa lại theo ý muốn
Mã:
Sub Gop_Dulieu()
Dim sArr1(), sArr2(), Dic As Object, Res()
Dim i As Long, k As Long, tmp As String, sArr(), n As Long, x As Long
Set Dic = CreateObject("scripting.dictionary")
With Sheets("DL1")
   sArr1 = .Range("B5", .Range("B" & Rows.Count).End(3)).Resize(, 9).Value
End With
With Sheets("DL2")
   sArr2 = .Range("B5", .Range("B" & Rows.Count).End(3)).Resize(, 9).Value
End With
sArr = Array(sArr1, sArr2)
ReDim Res(1 To (UBound(sArr1) + UBound(sArr2)), 1 To 9)
For n = LBound(sArr) To UBound(sArr)
   For i = 1 To UBound(sArr(n))
      If sArr(n)(i, 1) <> Empty Then
         tmp = sArr(n)(i, 1) & sArr(n)(i, 2) & sArr(n)(i, 3) & sArr(n)(i, 4) & sArr(n)(i, 5) & sArr(n)(i, 6)
         tmp = Replace(LCase(tmp), " ", "")
         If Not Dic.exists(tmp) Then
            k = k + 1
            Dic.Add tmp, k
            Res(k, 1) = sArr(n)(i, 1)
            Res(k, 2) = sArr(n)(i, 2)
            Res(k, 3) = sArr(n)(i, 3)
            Res(k, 4) = sArr(n)(i, 4)
            Res(k, 5) = sArr(n)(i, 5)
            Res(k, 6) = sArr(n)(i, 6)
            Res(k, n + 7) = sArr(n)(i, 8) 'lay so luong
            Res(k, 9) = sArr(n)(i, 9) 'thanh tien
         Else
            x = Dic.Item(tmp)
            Res(x, n + 7) = Res(x, n + 7) + sArr(n)(i, 8) 'cong don so luong
            Res(x, 9) = Res(x, 9) + sArr(n)(i, 9) 'cong don thanh tien
         End If
      End If
   Next
   k = k + 1
Next
Sheets("GOP").Range("B5").Resize(k, 9) = Res 'gan ket qua xuong sheet
End Sub
 
Upvote 0
Web KT

Bài viết mới nhất

Back
Top Bottom