Dictionary với item trùng

Liên hệ QC

Minh Ngọc LH

Thành viên chính thức
Tham gia
14/7/18
Bài viết
71
Được thích
32
Giới tính
Nữ
Mong các thành viên diễn đàn giúp em vấn đề này
Em cần tính cột Số lượng cộng dồn, thành tiền cộng dồn theo từng ngày của các sheet 1,2,3,4 từ sheet TONGHOP (vùng bôi màu vàng)
Em đang tính dùng Dictionary để tính, mà coi đi coi lại thấy không nhắm được điều kiện nào là duy nhất. Nhưng nếu kết hợp 3 điều kiện: Ngày, Cửa hàng và Sản phẩm lại thì chắc chắn không trùng. Ví dụ: chỉ có duy nhất một dòng cho cửa hàng 1, sản phẩm A tại ngày 1. Nhưng lại không được dùng cột phụ để nối 3 cột đó lại được vì form mẫu của người khác gửi báo cáo hàng ngày.
Các thành viên giúp em bằng dictionary hoặc mảng cũng được, miễn sao code chạy nhanh xíu vì dữ liệu này chỉ là giả định, thực tế gần giống vậy nhưng nhiều dòng và nhiều ngày hơn
Em cảm ơn!
 

File đính kèm

Mong các thành viên diễn đàn giúp em vấn đề này
Em cần tính cột Số lượng cộng dồn, thành tiền cộng dồn theo từng ngày của các sheet 1,2,3,4 từ sheet TONGHOP (vùng bôi màu vàng)
Em đang tính dùng Dictionary để tính, mà coi đi coi lại thấy không nhắm được điều kiện nào là duy nhất. Nhưng nếu kết hợp 3 điều kiện: Ngày, Cửa hàng và Sản phẩm lại thì chắc chắn không trùng. Ví dụ: chỉ có duy nhất một dòng cho cửa hàng 1, sản phẩm A tại ngày 1. Nhưng lại không được dùng cột phụ để nối 3 cột đó lại được vì form mẫu của người khác gửi báo cáo hàng ngày.
Các thành viên giúp em bằng dictionary hoặc mảng cũng được, miễn sao code chạy nhanh xíu vì dữ liệu này chỉ là giả định, thực tế gần giống vậy nhưng nhiều dòng và nhiều ngày hơn
Em cảm ơn!
Bạn chạy code này xem đúng không nhé.
Mã:
Sub tinhtong()
     Dim sh As Worksheet, arr, arr1, lr As Long, i As Long, dk As String, dic As Object, lr1 As Long, a As Long
     Set dic = CreateObject("scripting.dictionary")
     With Sheets("Tonghop")
          lr = .Range("B" & Rows.Count).End(xlUp).Row
          If lr < 3 Then Exit Sub
          .Range("E3:F" & lr).ClearContents
          arr = .Range("B3:F" & lr).Value
          For i = 1 To UBound(arr, 1)
              dk = arr(i, 1) & "#" & arr(i, 2) & "#" & arr(i, 3)
              dic.Item(dk) = i
          Next i
    End With
    For Each sh In ThisWorkbook.Worksheets
        If sh.Name <> "TONGHOP" Then
           lr1 = sh.Range("B" & Rows.Count).End(xlUp).Row
           If lr1 > 3 Then
              arr1 = sh.Range("B4:H" & lr1).Value
              For i = 1 To UBound(arr1, 1)
                  dk = arr1(i, 1) & "#" & arr1(i, 2) & "#" & arr1(i, 3)
                  a = dic.Item(dk)
                  If a Then
                     arr(a, 4) = arr1(i, 4) + arr(a, 4)
                     arr(a, 5) = arr1(i, 7) + arr(a, 5)
                  End If
              Next i
          End If
      End If
   Next
   With Sheets("Tonghop")
       .Range("B3:F" & lr).Value = arr
   End With
End Sub
 
Upvote 0
Bạn chạy code này xem đúng không nhé.
Mã:
Sub tinhtong()
     Dim sh As Worksheet, arr, arr1, lr As Long, i As Long, dk As String, dic As Object, lr1 As Long, a As Long
     Set dic = CreateObject("scripting.dictionary")
     With Sheets("Tonghop")
          lr = .Range("B" & Rows.Count).End(xlUp).Row
          If lr < 3 Then Exit Sub
          .Range("E3:F" & lr).ClearContents
          arr = .Range("B3:F" & lr).Value
          For i = 1 To UBound(arr, 1)
              dk = arr(i, 1) & "#" & arr(i, 2) & "#" & arr(i, 3)
              dic.Item(dk) = i
          Next i
    End With
    For Each sh In ThisWorkbook.Worksheets
        If sh.Name <> "TONGHOP" Then
           lr1 = sh.Range("B" & Rows.Count).End(xlUp).Row
           If lr1 > 3 Then
              arr1 = sh.Range("B4:H" & lr1).Value
              For i = 1 To UBound(arr1, 1)
                  dk = arr1(i, 1) & "#" & arr1(i, 2) & "#" & arr1(i, 3)
                  a = dic.Item(dk)
                  If a Then
                     arr(a, 4) = arr1(i, 4) + arr(a, 4)
                     arr(a, 5) = arr1(i, 7) + arr(a, 5)
                  End If
              Next i
          End If
      End If
   Next
   With Sheets("Tonghop")
       .Range("B3:F" & lr).Value = arr
   End With
End Sub
Hiều nhầm ý rồi anh @snow25 :)
Em cần tính là các cột bôi màu vàng của các sheet 1,2,3,4
Còn Sheet TONGHOP là có sẵn rồi, không cần tính nữa
Ví dụ: Tại sheet 2 sẽ tính tổng cộng dồn số lượng và thành tiền từ ngày 1 đến ngày 2 của từng sản phẩm cho từng cửa hàng, tương tự ngày 3 sẽ là cộng dồn của ngày 1,2,3. Dữ liệu được lấy từ sheet TONGHOP
 
Upvote 0
Hiều nhầm ý rồi anh @snow25 :)
Em cần tính là các cột bôi màu vàng của các sheet 1,2,3,4
Còn Sheet TONGHOP là có sẵn rồi, không cần tính nữa
Ví dụ: Tại sheet 2 sẽ tính tổng cộng dồn số lượng và thành tiền từ ngày 1 đến ngày 2 của từng sản phẩm cho từng cửa hàng, tương tự ngày 3 sẽ là cộng dồn của ngày 1,2,3. Dữ liệu được lấy từ sheet TONGHOP
À làm ngược à có tổng rồi.Giờ chia ra à.
 
Upvote 0
Hiều nhầm ý rồi anh @snow25 :)
Em cần tính là các cột bôi màu vàng của các sheet 1,2,3,4
Còn Sheet TONGHOP là có sẵn rồi, không cần tính nữa
Ví dụ: Tại sheet 2 sẽ tính tổng cộng dồn số lượng và thành tiền từ ngày 1 đến ngày 2 của từng sản phẩm cho từng cửa hàng, tương tự ngày 3 sẽ là cộng dồn của ngày 1,2,3. Dữ liệu được lấy từ sheet TONGHOP
Đúng là câu hỏi không rõ ràng.
 

File đính kèm

Upvote 0
Hiều nhầm ý rồi anh @snow25 :)
Em cần tính là các cột bôi màu vàng của các sheet 1,2,3,4
Còn Sheet TONGHOP là có sẵn rồi, không cần tính nữa
Ví dụ: Tại sheet 2 sẽ tính tổng cộng dồn số lượng và thành tiền từ ngày 1 đến ngày 2 của từng sản phẩm cho từng cửa hàng, tương tự ngày 3 sẽ là cộng dồn của ngày 1,2,3. Dữ liệu được lấy từ sheet TONGHOP
Vậy bạn chạy code này xem nhé.
Mã:
Sub tinhtong()
     Dim sh As Worksheet, arr, arr1, lr As Long, i As Long, dk As String, dic As Object, lr1 As Long, a As Long
     Set dic = CreateObject("scripting.dictionary")
     With Sheets("Tonghop")
          lr = .Range("B" & Rows.Count).End(xlUp).Row
          If lr < 3 Then Exit Sub
          arr = .Range("B3:F" & lr).Value
          For i = 1 To UBound(arr, 1)
              dk = arr(i, 1) & "#" & arr(i, 2) & "#" & arr(i, 3)
              dic.Item(dk) = i
          Next i
    End With
    For Each sh In ThisWorkbook.Worksheets
        If sh.Name <> "TONGHOP" Then
           lr1 = sh.Range("B" & Rows.Count).End(xlUp).Row
           If lr1 > 3 Then
              arr1 = sh.Range("B4:i" & lr1).Value
              sh.Range("F4:F" & lr1).ClearContents
              sh.Range("I4:I" & lr1).ClearContents
              For i = 1 To UBound(arr1, 1)
                  dk = arr1(i, 1) & "#" & arr1(i, 2) & "#" & arr1(i, 3)
                  a = dic.Item(dk)
                  If a Then
                     arr1(i, 5) = arr(a, 4) +arr1(i, 5)
                     arr1(i, 8) = arr(a, 5) +arr1(i, 8)
                  End If
              Next i
              sh.Range("B4:i" & lr1).Value = arr1
          End If
      End If
   Next
End Sub
 
Upvote 0
Mong các thành viên diễn đàn giúp em vấn đề này
Em cần tính cột Số lượng cộng dồn, thành tiền cộng dồn theo từng ngày của các sheet 1,2,3,4 từ sheet TONGHOP (vùng bôi màu vàng)
Em đang tính dùng Dictionary để tính, mà coi đi coi lại thấy không nhắm được điều kiện nào là duy nhất. Nhưng nếu kết hợp 3 điều kiện: Ngày, Cửa hàng và Sản phẩm lại thì chắc chắn không trùng. Ví dụ: chỉ có duy nhất một dòng cho cửa hàng 1, sản phẩm A tại ngày 1. Nhưng lại không được dùng cột phụ để nối 3 cột đó lại được vì form mẫu của người khác gửi báo cáo hàng ngày.
Các thành viên giúp em bằng dictionary hoặc mảng cũng được, miễn sao code chạy nhanh xíu vì dữ liệu này chỉ là giả định, thực tế gần giống vậy nhưng nhiều dòng và nhiều ngày hơn
Em cảm ơn!
Sheet "TONG HOP" có lẽ đổi tên thành "Số liệu" thì phù hợp hơn
 
Upvote 0
Vậy bạn chạy code này xem nhé.
Cảm ơn anh
Anh có thể kiểm tra lại chút xíu được không vì nó không tính cộng dồn mà chỉ mới bằng đúng ngày hiện hành thôi
Đúng là câu hỏi không rõ ràng.
Cảm ơn Thầy, code cho kết quả đúng rồi, nhưng Thầy có thể chỉ cho nó chạy trên vùng được bôi màu vàng thay vì toàn bộ sheet được không ạ
Vì dữ liệu nó đi vòng vòng như thế này: Người làm báo cáo sẽ nhập dữ liệu trong các sheet 1,2,3,4 nhưng không nhập tại vùng màu vàng
Sau đó tất cả dữ liệu được nhập đó sẽ được đưa về sheet TONGHOP, và lúc đó cột màu vàng của từng sheet 1,2,3,4 sẽ được tính từ sheet TONGHOP.
Em chỉ cần tính màu vàng thôi
Bài đã được tự động gộp:

Sheet "TONG HOP" có lẽ đổi tên thành "Số liệu" thì phù hợp hơn
Sheet TONGHOP sẽ lấy toàn bộ dữ liệu nhập hàng ngày tại các sheet 1,2,3,4 nhưng không bao gồm vùng đang cần tính tổng cộng dồn. Nếu đặt tên là tập hợp dữ liệu thì hợp lý hơn :)
 
Upvote 0
Cảm ơn anh
Anh có thể kiểm tra lại chút xíu được không vì nó không tính cộng dồn mà chỉ mới bằng đúng ngày hiện hành thôi

Cảm ơn Thầy, code cho kết quả đúng rồi, nhưng Thầy có thể chỉ cho nó chạy trên vùng được bôi màu vàng thay vì toàn bộ sheet được không ạ
Vì dữ liệu nó đi vòng vòng như thế này: Người làm báo cáo sẽ nhập dữ liệu trong các sheet 1,2,3,4 nhưng không nhập tại vùng màu vàng
Sau đó tất cả dữ liệu được nhập đó sẽ được đưa về sheet TONGHOP, và lúc đó cột màu vàng của từng sheet 1,2,3,4 sẽ được tính từ sheet TONGHOP.
Em chỉ cần tính màu vàng thôi
Bài đã được tự động gộp:


Sheet TONGHOP sẽ lấy toàn bộ dữ liệu nhập hàng ngày tại các sheet 1,2,3,4 nhưng không bao gồm vùng đang cần tính tổng cộng dồn. Nếu đặt tên là tập hợp dữ liệu thì hợp lý hơn :)
Bạn xem lại mình sửa rồi mà.
 
Upvote 0
Bạn xem lại mình sửa rồi mà.
Dạ, đã thấy cộng dồn, nhưng nếu bấm chạy code thêm vài lần nó lại làm tăng số cộng dồn lên nữa, không biết là tại sao nhỉ. Thấy có
ClearContents vùng cộng dồn rồi mà
Bài đã được tự động gộp:

dk = arr(i, 1) & "#" & arr(i, 2) & "#" & arr(i, 3) dic.Item(dk) = i
Khúc này của anh snow25 hay nè, nối điều kiện lại để được 1 điều kiện không trùng
 
Upvote 0
Dạ, đã thấy cộng dồn, nhưng nếu bấm chạy code thêm vài lần nó lại làm tăng số cộng dồn lên nữa, không biết là tại sao nhỉ. Thấy có
ClearContents vùng cộng dồn rồi mà
Bài đã được tự động gộp:


Khúc này của anh snow25 hay nè, nối điều kiện lại để được 1 điều kiện không trùng
À bạn đảo cái này là được nhé.Mình làm ngược.Phải xóa xong thì mới lấy giá trị.
Mã:
sh.Range("F4:F" & lr1).ClearContents
              sh.Range("I4:I" & lr1).ClearContents
Mã:
arr1 = sh.Range("B4:i" & lr1).Value
 
Upvote 0
À bạn đảo cái này là được nhé.Mình làm ngược.Phải xóa xong thì mới lấy giá trị.
Mã:
sh.Range("F4:F" & lr1).ClearContents
              sh.Range("I4:I" & lr1).ClearContents
Mã:
arr1 = sh.Range("B4:i" & lr1).Value
Dạ, để em ngâm cứu vì nó vẫn có cái gì đó không ổn
Khúc này
Mã:
                     arr1(i, 5) = arr(a, 4) +arr1(i, 5)
                     arr1(i, 8) = arr(a, 5) +arr1(i, 8)

vì nếu gom cả 3 điều kiện vào làm 1 thì đương nhiên dic nó hiểu là ngày 2 không giống ngày 1, mà mình lại cần ngày 2 phải cộng dồn của cả ngày 1 nữa, ngày 3 thì cộng dồn ngày 1 và 2. còn code hiện tại arr(a, 4) nó không còn điều kiện nào giống arr1(i, 5) để cộng dồn
Ngoài ra, có cần set Dic = nothing không anh
Cảm ơn anh nhiều!
 
Upvote 0
Muốn dùng công thức, có thể sử dụng chung cho tất cả các sheet từ 1 đến 31:

Cột số lượng:

Mã:
=SUMIFS(TONGHOP!E:E,TONGHOP!B:B,"<="&B4,TONGHOP!C:C,C4,TONGHOP!D:D,D4)

Cột thành tiền:

Mã:
=SUMIFS(TONGHOP!F:F,TONGHOP!B:B,"<="&B4,TONGHOP!C:C,C4,TONGHOP!D:D,D4)
 
Upvote 0
Muốn dùng công thức, có thể sử dụng chung cho tất cả các sheet từ 1 đến 31:

Cột số lượng:

Mã:
=SUMIFS(TONGHOP!E:E,TONGHOP!B:B,"<="&B4,TONGHOP!C:C,C4,TONGHOP!D:D,D4)

Cột thành tiền:

Mã:
=SUMIFS(TONGHOP!F:F,TONGHOP!B:B,"<="&B4,TONGHOP!C:C,C4,TONGHOP!D:D,D4)
Công thức thì em tự làm được bác ơi. File thực tế rất nhiều dữ liệu nên chạy nhiều công thức nó đã quá chậm rồi
Em đang mày mò VBA cho nó nhanh xíu
 
Upvote 0
Công thức thì em tự làm được bác ơi. File thực tế rất nhiều dữ liệu nên chạy nhiều công thức nó đã quá chậm rồi
Em đang mày mò VBA cho nó nhanh xíu
Nếu tôi thiết kế, tôi chỉ làm một sheet cho 31 ngày, chỉ cần thay đổi ngày là có một báo cáo cộng dồn, kể cả dùng VBA.
 
Upvote 0
Upvote 0
Dạ, để em ngâm cứu vì nó vẫn có cái gì đó không ổn
Khúc này
Mã:
                     arr1(i, 5) = arr(a, 4) +arr1(i, 5)
                     arr1(i, 8) = arr(a, 5) +arr1(i, 8)

vì nếu gom cả 3 điều kiện vào làm 1 thì đương nhiên dic nó hiểu là ngày 2 không giống ngày 1, mà mình lại cần ngày 2 phải cộng dồn của cả ngày 1 nữa, ngày 3 thì cộng dồn ngày 1 và 2. còn code hiện tại arr(a, 4) nó không còn điều kiện nào giống arr1(i, 5) để cộng dồn
Ngoài ra, có cần set Dic = nothing không anh
Cảm ơn anh nhiều!
Gửi Bạn xem lại nhé.Câu lệnh này set Dic = nothing là Để giải phóng bộ nhớ.Nhưng mà đây là mình khai báo thế này thì khi chạy hết code biến tự giải phóng bạn à.Mình đoán vậy.
Mã:
Sub tinhtong()
     Dim sh As Worksheet, arr, arr1, lr As Long, i As Long, dk As String, dic As Object, lr1 As Long, a As Double, b As Double
     Set dic = CreateObject("scripting.dictionary")
     With Sheets("Tonghop")
          lr = .Range("B" & Rows.Count).End(xlUp).Row
          If lr < 3 Then Exit Sub
          arr = .Range("B3:F" & lr).Value
          For i = 1 To UBound(arr, 1)
              dk = arr(i, 1) & "#" & arr(i, 2) & "#" & arr(i, 3)
              If Not dic.exists(dk) Then
                 dic.Add dk, Array(arr(i, 4), arr(i, 5))
              Else
                 a = dic.Item(dk)(0)
                 b = dic.Item(dk)(1)
              End If
          Next i
    End With
    For Each sh In ThisWorkbook.Worksheets
        If sh.Name <> "TONGHOP" Then
           lr1 = sh.Range("B" & Rows.Count).End(xlUp).Row
           If lr1 > 3 Then
               sh.Range("F4:F" & lr1).ClearContents
              sh.Range("I4:I" & lr1).ClearContents
              arr1 = sh.Range("B4:i" & lr1).Value
              For i = 1 To UBound(arr1, 1)
                   a = 0
                   b = 0
                   For k = 1 To arr1(i, 1)
                       dk = k & "#" & arr1(i, 2) & "#" & arr1(i, 3)
                       If dic.exists(dk) Then
                          a = a + dic.Item(dk)(0)
                          b = b + dic.Item(dk)(1)
                       End If
                   Next k
                   arr1(i, 5) = a
                   arr1(i, 8) = b
              Next i
              sh.Range("B4:i" & lr1).Value = arr1
          End If
      End If
   Next
End Sub
 
Lần chỉnh sửa cuối:
Upvote 0
Form
Gửi Bạn xem lại nhé.Câu lệnh này set Dic = nothing là Để giải phóng bộ nhớ.Nhưng mà đây là mình khai báo thế này thì khi chạy hết code biến tự giải phóng bạn à.Mình đoán vậy.
Mã:
Sub tinhtong()
     Dim sh As Worksheet, arr, arr1, lr As Long, i As Long, dk As String, dic As Object, lr1 As Long, a As Double, b As Double
     Set dic = CreateObject("scripting.dictionary")
     With Sheets("Tonghop")
          lr = .Range("B" & Rows.Count).End(xlUp).Row
          If lr < 3 Then Exit Sub
          arr = .Range("B3:F" & lr).Value
          For i = 1 To UBound(arr, 1)
              dk = arr(i, 1) & "#" & arr(i, 2) & "#" & arr(i, 3)
              If Not dic.exists(dk) Then
                 dic.Add dk, Array(arr(i, 4), arr(i, 5))
              Else
                 a = dic.Item(dk)(0)
                 b = dic.Item(dk)(1)
              End If
          Next i
    End With
    For Each sh In ThisWorkbook.Worksheets
        If sh.Name <> "TONGHOP" Then
           lr1 = sh.Range("B" & Rows.Count).End(xlUp).Row
           If lr1 > 3 Then
               sh.Range("F4:F" & lr1).ClearContents
              sh.Range("I4:I" & lr1).ClearContents
              arr1 = sh.Range("B4:i" & lr1).Value
              For i = 1 To UBound(arr1, 1)
                   a = 0
                   b = 0
                   For k = 1 To arr1(i, 1)
                       dk = k & "#" & arr1(i, 2) & "#" & arr1(i, 3)
                       If dic.exists(dk) Then
                          a = a + dic.Item(dk)(0)
                          b = b + dic.Item(dk)(1)
                       End If
                   Next k
                   arr1(i, 5) = a
                   arr1(i, 8) = b
              Next i
              sh.Range("B4:i" & lr1).Value = arr1
          End If
      End If
   Next
End Sub
Vừa test qua kết quả thấy chuẩn rồi, cảm ơn anh nhiều!
 
Upvote 0
Form

Vừa test qua kết quả thấy chuẩn rồi, cảm ơn anh nhiều!
Bạn chỉnh lại chỗ này nhé.Quyên không viết vào.
Mã:
Sub tinhtong()
     Dim sh As Worksheet, arr, arr1, lr As Long, i As Long, dk As String, dic As Object, lr1 As Long, a As Double, b As Double
     Set dic = CreateObject("scripting.dictionary")
     With Sheets("Tonghop")
          lr = .Range("B" & Rows.Count).End(xlUp).Row
          If lr < 3 Then Exit Sub
          arr = .Range("B3:F" & lr).Value
          For i = 1 To UBound(arr, 1)
              dk = arr(i, 1) & "#" & arr(i, 2) & "#" & arr(i, 3)
              If Not dic.exists(dk) Then
                 dic.Add dk, Array(arr(i, 4), arr(i, 5))
              Else
                 a = dic.Item(dk)(0)
                 b = dic.Item(dk)(1)
                 a=a+arr(i,4)              Thêm câu này nhé.Giờ mới nhìn ra'
                 b=b+arr(i,5)              Thêm câu này nhé.Giờ mới nhìn ra'
                 Dic.item(dk)=array(a,b)   'Thêm câu này nhé.Giờ mới nhìn ra'
              End If
          Next i
    End With
    For Each sh In ThisWorkbook.Worksheets
        If sh.Name <> "TONGHOP" Then
           lr1 = sh.Range("B" & Rows.Count).End(xlUp).Row
           If lr1 > 3 Then
               sh.Range("F4:F" & lr1).ClearContents
              sh.Range("I4:I" & lr1).ClearContents
              arr1 = sh.Range("B4:i" & lr1).Value
              For i = 1 To UBound(arr1, 1)
                   a = 0
                   b = 0
                   For k = 1 To arr1(i, 1)
                       dk = k & "#" & arr1(i, 2) & "#" & arr1(i, 3)
                       If dic.exists(dk) Then
                          a = a + dic.Item(dk)(0)
                          b = b + dic.Item(dk)(1)
                       End If
                   Next k
                   arr1(i, 5) = a
                   arr1(i, 8) = b
              Next i
              sh.Range("B4:i" & lr1).Value = arr1
          End If
      End If
   Next
End Sub
 
Upvote 0
Web KT

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

Back
Top Bottom