Nhờ tính tổng cho từng sản phẩm do từng công ty làm được bằng VBA

  • Thread starter Thread starter LinDan
  • Ngày gửi Ngày gửi
Liên hệ QC

LinDan

Thành viên tiêu biểu
Tham gia
8/2/12
Bài viết
412
Được thích
111
Bà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.

Tonghopdulieu.png


Xin cảm ơn rất nhiều
 

File đính kèm

Lần chỉnh sửa cuối:
Code của thày chạy ra nó vẫn không được kết quả Sản phẩm 3 (chỉ ra sản phẩm 1 và 2) thôi.

Bản thân tôi cứ tưởng có 4 If thì có 4 End If là được, 4 End If này đặt đâu cũng thế vì không thấy lỗi.
 
Lần chỉnh sửa cuối:
Upvote 0
Code của thày chạy ra nó vẫn không được kết quả Sản phẩm 3 (chỉ ra sản phẩm 1 và 2) thôi.

Bản thân tôi cứ tưởng có 4 If thì có 4 End If là được, 4 End If này đặt đâu cũng thế vì không thấy lỗi.
Ah.. sơ ý!
Sửa chổ này:
.[A1].Resize(Dong, Cot).Value = KQ
Thành:
.[A1].Resize(n, m).Value = KQ
 
Upvote 0
Bản thân chưa phân biệt được 2 Code này khác nhau ở điểm gì, mong bác Ndu chỉ giúp
Code đúng:
PHP:
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(m, n).Value = KQ
  End With
End Sub
Code tính sai:
PHP:
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
        Dong = Dic1.Item(Tmp1)
        KQ(n, 1) = Tmp1
      End If
      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
      End If
      
      KQ(Dong, Cot) = KQ(Dong, Cot) + DL(i, 3)
    End If
  Next
  With Sheets("Sheet2")
    .Cells.ClearContents
    .[A1].Resize(m, n).Value = KQ
  End With
End Sub

Ghi chú: 2 Code trên khác nhau là do thứ tự đặt 2 lệnh vị trí khác nhau
PHP:
            Dong = Dic1.Item(Tmp1)
      Cot = Dic2.Item(Tmp2)
nhưng chưa hình dung được khi hoạt động thì nó khác nhau như thế nào nhỉ?
 
Lần chỉnh sửa cuối:
Upvote 0
Ghi chú: 2 Code trên khác nhau là do thứ tự đặt 2 lệnh vị trí khác nhau
PHP:
            Dong = Dic1.Item(Tmp1)
      Cot = Dic2.Item(Tmp2)
nhưng chưa hình dung được khi hoạt động thì nó khác nhau như thế nào nhỉ?
- Khi bạn duyệt qua vòng lập từ trên xuống, bạn Add từng cái tmp1 vào Dic1 và tmp2 vào Dic2, đúng không?
- tmp1 và tmp2 chỉ Add được khi Dictionary chưa tồn tại mấy thằng em này, đúng không?
- Nhưng cho dù là Add được vào Dictionary hay không thì bạn cũng phải xác định Dong, Cot để cộng dồn vào KQ
- Vậy có phải là việc xác định Dong, Cot và cộng dồn này phải nằm ngoài IF không?
Chẳng lẽ "chưa tồn tại" thì mới cộng dồn còn "tồn tại" rồi, khỏi cộng?
 
Upvote 0
Vâng vâng, chỗ này có khi tôi chưa hiểu lắm về Dic thì phải, nhất trí KQ phải cộng sau End If rồi, nhưng Dong và Cot có thể đã xác định trước End If cũng được chứ hả bác.

Xin bác hộ cho tôi hiểu chỗ này với.
 
Upvote 0
Vâng vâng, chỗ này có khi tôi chưa hiểu lắm về Dic thì phải, nhất trí KQ phải cộng sau End If rồi, nhưng Dong và Cot có thể đã xác định trước End If cũng được chứ hả bác.

Xin bác hộ cho tôi hiểu chỗ này với.
KQ muốn cộng dồn được thì phải xác định Dong, Cot trước, đúng không? Vì KQ(Dong, Cot) = KQ(Dong, Cot) + DL(i, 3)
Vậy, nếu cho biến Dong, Cot vào bên trong IF, ở trường hợp IF không thỏa điều kiện thì hóa ra sẽ lấy Dong, Cot của lần trước à?
 
Upvote 0
Thế thì 2 cách viết như sau là hoàn toàn khác nhau hả bác. Tôi cứ tưởng nó giống nhau chứ
PHP:
If Not Dic2.Exists(Tmp2) Then
        m = m + 1
        Dic2.Add Tmp2, m
        KQ(1, m) = Tmp2
      Cot = Dic2.Item(Tmp2)
End If

và cách viết
PHP:
If Not Dic2.Exists(Tmp2) Then
        m = m + 1
        Dic2.Add Tmp2, m
        KQ(1, m) = Tmp2
      End If
            Cot = Dic2.Item(Tmp2)
 
Upvote 0
Cái này thày nói quá rõ ở trên rồi mà, bây giờ ta bàn đến trường hợp khi duyệt qua gặp lại phần tử trước nhé.

Cách viết này
PHP:
If Not Dic2.Exists(Tmp2) Then
        m = m + 1
        Dic2.Add Tmp2, m
        KQ(1, m) = Tmp2
      End If
            Cot = Dic2.Item(Tmp2)

có nghĩa là sau khi họp, xem xét xong (sau khi End If) thấy Tmp2 này đã gặp rồi>> nó vẫn phải lấy mã số cũ.
Cách viết này m và Cot độc lập nhau. Ví dụ khi i=11 thì m=5 nhưng i = 2

Do dòng Cot = Dic2.Item(Tmp2) nằm ngoài lệnh If nên lúc này nó chính là Item của Tmp2 (mới)
-------------------------
Còn cách viết này
PHP:
If Not Dic2.Exists(Tmp2) Then
        m = m + 1
        Dic2.Add Tmp2, m
        KQ(1, m) = Tmp2
      Cot = Dic2.Item(Tmp2)
End If
lúc này Tmp2 do không nhét được vào, do Cot nằm trong If nên nó không lấy được Item của Tmp2 mới>> đành phải lấy Item của Tmp2, cách viết này thì Cot luôn luôn bằng m (cột =m). Ví dụ khi i=11 thì m=5, cot=5.

Cái này nói rõ hơi khó nhưng bạn cứ chịu khó tưởng tượng sẽ ra thôi.
 
Lần chỉnh sửa cuối:
Upvote 0
Thế thì 2 cách viết như sau là hoàn toàn khác nhau hả bác. Tôi cứ tưởng nó giống nhau chứ
PHP:
If Not Dic2.Exists(Tmp2) Then
        m = m + 1
        Dic2.Add Tmp2, m
        KQ(1, m) = Tmp2
      Cot = Dic2.Item(Tmp2)
End If

và cách viết
PHP:
If Not Dic2.Exists(Tmp2) Then
        m = m + 1
        Dic2.Add Tmp2, m
        KQ(1, m) = Tmp2
      End If
            Cot = Dic2.Item(Tmp2)

2 cách viết đương nhiên khác nhau, VBA sẽ làm việc theo thứ tự trên xuống dưới. Nếu với cách viết 1 của bạn thì là điều kiện thỏa thì mới thực hiện, còn cách thứ 2 thì dù thỏa hay không cũng làm vì nó được đặt ngoài vòng If rồi. Bạn có thể hiểu rõ hơn bằng cách sử dụng F8 đấy, khi bạn nhấn F8 thì nó sẽ thực hiện từng dòng lệnh một và bạn sẽ thấy rõ nó làm cái gì làm cái gì, khi đó bạn có thể hiểu hơn về cách vận hành của chương trình
 
Upvote 0
Giải thích như bác kyo là chuẩn, dễ hiểu quá rồi.
 
Upvote 0
Giải thích như bác kyo là chuẩn, dễ hiểu quá rồi.

Tôi phải công nhận bạn cũng là một thiên tài! Chưa rành về IF, WITH, ... , các sự kiện của Sheet, ... vậy mà bạn đã học gần như có thể làm được các vụ xử lý trong mảng rồi, đặc biệt là Dictionary.

Bạn đã chọn một trong những con đường khó nhất để đi trong lập trình VBA. Xin chúc mừng bạn!
 
Upvote 0
Web KT

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

Back
Top Bottom