Tổng hợp dữ liệu (Sử dụng Dictionary)

Liên hệ QC

tueyennhi

Thành viên tích cực
Tham gia
18/10/10
Bài viết
1,192
Được thích
105
Chào anh chị, cho em hỏi: Em có sheets KQ và TH (với TH là tổng hợp tất cả dữ liệu). Làm thế nào em có thể lấy kết quả tại sheet KQ theo ý muốn với cột A là mã duy nhất và dòng 2 từ cột B là cột muốn lấy (em muốn khi em thay đổi con số cột hoặc mã duy nhất thì kết quả thay đổi theo sau khi chạy code). Em cảm ơn.

PHP:
Option Explicit
Private Sub TnDic()
    Dim Dic As Object, Col As Object, Ws As Worksheet, Tem As String, Rws As Long
    Dim R As Long, i As Long, j As Long, k As Long, C As Long, h As Long
    Dim sArr As Variant, dArr(1 To 500, 1 To 50)
    
    Set Dic = CreateObject("Scripting.Dictionary")
    Set Col = CreateObject("Scripting.Dictionary")
    
    
    Application.ScreenUpdating = False
    Application.EnableEvents = False
    Application.Calculation = xlCalculationManual
    
    With Sheets("KQ")
        'Cot
        sArr = .Range("A2").Resize(100, 10).Value
        For j = 2 To 10
            If sArr(1, j) <> Empty Then
                 Col.Item(Day(sArr(1, j))) = j - 1
            End If
        Next j
        'Dong
        For j = 2 To 100
            If sArr(j, 1) <> Empty Then
                 Dic.Add sArr(j, 1), j - 1
            End If
        Next j
        
    End With
    
    With Sheets("TH")
        sArr = .Range("A6", .Range("A65000").End(xlUp)).Resize(, 50).Value2
        For j = 2 To UBound(sArr, 2)
            C = Col.Item(sArr(1, j))
            For i = 2 To UBound(sArr, 1)
                Tem = sArr(i, 1)
                If Len(sArr(i, 1)) > 0 Then
                    If Dic.Exists(Tem) Then
                        Rws = Dic.Item(Tem)
                        dArr(Rws, C) = sArr(i, j)
                    End If
                End If
            Next i
        Next j
    End With
    
    Sheets("KQ").Range("B3").Resize(10, 10) = dArr
    Set Dic = Nothing
    Set Col = Nothing
 
    Application.ScreenUpdating = True
    Application.EnableEvents = True
    Application.Calculation = xlCalculationAutomatic
   
End Sub

Em có thử viết code sau mà loay hoay mãi không biết sai ở đâu.
 

File đính kèm

Lần chỉnh sửa cuối:
Em làm được rồi. Hì hụi mãi :(
PHP:
Option Explicit
Private Sub TnDic()
    Dim Dic As Object, Col As Object, Ws As Worksheet, Tem As String, Rws As Long
    Dim R As Long, i As Long, j As Long, k As Long, C As Long, h As Long, k1 As Long, k2 As Long
    Dim sArr As Variant, dArr(1 To 500, 1 To 50)
    
    Set Dic = CreateObject("Scripting.Dictionary")
    Set Col = CreateObject("Scripting.Dictionary")
    
    
    Application.ScreenUpdating = False
    Application.EnableEvents = False
    Application.Calculation = xlCalculationManual
    
    With Sheets("KQ")
        'Cot
        sArr = .Range("B2").Resize(, 10).Value
        For i = 1 To 10
            Tem = sArr(1, i)
            If Len(Tem) > 0 And Not Col.Exists(Tem) Then
                 Col.Item(Tem) = i
            End If
        Next i
        k2 = i
        'Dong
        sArr = .Range("A3").Resize(10, 1).Value
        For i = 1 To 10
            Tem = sArr(i, 1)
            If Len(Tem) > 0 And Not Dic.Exists(Tem) Then
                Dic.Add Tem, i
            End If
        Next i
        k1 = i
    End With
   
    With Sheets("TH")
        sArr = .Range("A6", .Range("A65000").End(xlUp)).Resize(, 50).Value2
        For i = 2 To UBound(sArr, 1)
            Tem = sArr(i, 1)
            If Dic.Exists(Tem) Then
                Rws = Dic.Item(Tem)
                For j = 2 To UBound(sArr, 2)
                    Tem = sArr(1, j)
                    If Col.Exists(Tem) Then
                        C = Col.Item(Tem)
                        dArr(Rws, C) = sArr(i, j)
                    End If
                Next j
            End If
        Next i
    End With
    
    Sheets("KQ").Range("B3").Resize(k1, k2) = dArr
    Set Dic = Nothing
    Set Col = Nothing
 
    Application.ScreenUpdating = True
    Application.EnableEvents = True
    Application.Calculation = xlCalculationAutomatic
   
End Sub
 
Upvote 0
Đây là 1 dạng cộng cả ngang và dọc nhiều điều kiện !. Em hóng cách khác
 
Lần chỉnh sửa cuối:
Upvote 0
Cái kết của việc không nắm vững kiến thức cơ bản, giờ nhìn lại thấy thật ngốc nghếch.
 
Upvote 0
Em làm được rồi. Hì hụi mãi :(
PHP:
Option Explicit
Private Sub TnDic()
    Dim Dic As Object, Col As Object, Ws As Worksheet, Tem As String, Rws As Long
    Dim R As Long, i As Long, j As Long, k As Long, C As Long, h As Long, k1 As Long, k2 As Long
    Dim sArr As Variant, dArr(1 To 500, 1 To 50)
   
    Set Dic = CreateObject("Scripting.Dictionary")
    Set Col = CreateObject("Scripting.Dictionary")
   
   
    Application.ScreenUpdating = False
    Application.EnableEvents = False
    Application.Calculation = xlCalculationManual
   
    With Sheets("KQ")
        'Cot
        sArr = .Range("B2").Resize(, 10).Value
        For i = 1 To 10
            Tem = sArr(1, i)
            If Len(Tem) > 0 And Not Col.Exists(Tem) Then
                 Col.Item(Tem) = i
            End If
        Next i
        k2 = i
        'Dong
        sArr = .Range("A3").Resize(10, 1).Value
        For i = 1 To 10
            Tem = sArr(i, 1)
            If Len(Tem) > 0 And Not Dic.Exists(Tem) Then
                Dic.Add Tem, i
            End If
        Next i
        k1 = i
    End With
  
    With Sheets("TH")
        sArr = .Range("A6", .Range("A65000").End(xlUp)).Resize(, 50).Value2
        For i = 2 To UBound(sArr, 1)
            Tem = sArr(i, 1)
            If Dic.Exists(Tem) Then
                Rws = Dic.Item(Tem)
                For j = 2 To UBound(sArr, 2)
                    Tem = sArr(1, j)
                    If Col.Exists(Tem) Then
                        C = Col.Item(Tem)
                        dArr(Rws, C) = sArr(i, j)
                    End If
                Next j
            End If
        Next i
    End With
   
    Sheets("KQ").Range("B3").Resize(k1, k2) = dArr
    Set Dic = Nothing
    Set Col = Nothing

    Application.ScreenUpdating = True
    Application.EnableEvents = True
    Application.Calculation = xlCalculationAutomatic
  
End Sub
chẳng hiểu bạn dùng dictionary làm gì, :D bạn có thể giải thích cho mình được không
 
Upvote 0
chẳng hiểu bạn dùng dictionary làm gì, :D bạn có thể giải thích cho mình được không
Mình làm cái này để check số liệu với người khác. Số liệu đó ID thay đổi lúc vị trí dòng này lúc dòng khác nên dùng dic để xác định dòng, còn cột tùy vào công việc mình cần thay đổi cột nọ cột kia nên dùng thêm Dic để xác định cột thông qua code cột. Theo bạn có phương án nào khả thi hơn???
 
Upvote 0
@tueyennhi
Thấy mọi nguời thường nạp bảng tra vào Dic trước, sau đó mới trích số liệu cần thiết
Góp đoạn code
Mã:
Option Explicit
Public Sub TnDic()
    Dim Dic As Object, Col As Object, Ws As Worksheet, Tem As String, Rws As Long
    Dim R As Long, i As Long, j As Long, k As Long, C As Long, h As Long, k1 As Long, k2 As Long
    Dim sArr As Variant, dArr(1 To 500, 1 To 50)
    
    Set Dic = CreateObject("Scripting.Dictionary")
    'Set Col = CreateObject("Scripting.Dictionary")
    With Sheets("TH")
        sArr = .Range("A7").CurrentRegion
        For j = 2 To UBound(sArr, 2)
            If sArr(1, j) <> "" Then
                For i = 2 To UBound(sArr, 1)
                    Tem = sArr(i, 1) & " " & sArr(1, j)
                    If Dic.exists(Tem) = False Then
                        Dic.Add Tem, sArr(i, j)
                    End If
                Next i
            End If
        Next j
    End With
    Application.ScreenUpdating = False
    With Sheets("KQ")
        For j = 2 To .Range("XFD2").End(xlToLeft).Column
            If .Cells(2, j).Value <> "" Then
                For i = 3 To .Range("A65000").End(xlUp).Row
                    Tem = .Cells(i, 1).Value & " " & .Cells(2, j)
                    If Dic.exists(Tem) = True Then
                        .Cells(i, j) = Dic.Item(Tem)
                    End If
                Next i
            End If
        Next j
    End With
    Application.ScreenUpdating = True
End Sub
 
Upvote 0
Thấy mọi nguời thường ...
Thấy mọi người thường ... dùng Tem để gọi một cái biến mà họ không muốn đặt tên nghiêm chỉnh.
Thực tế, nó chỉ là một cái biến. Về tính chất "tạm bợ/temporary" nó không hẳn đạt yêu cầu. Tại sao không gọi thẳng là key cho đúng theo nhiệm vụ của nó. Hoặc là var (variable/biến)
 
Upvote 0
Thấy mọi người thường ... dùng Tem để gọi một cái biến mà họ không muốn đặt tên nghiêm chỉnh.
Thực tế, nó chỉ là một cái biến. Về tính chất "tạm bợ/temporary" nó không hẳn đạt yêu cầu. Tại sao không gọi thẳng là key cho đúng theo nhiệm vụ của nó. Hoặc là var (variable/biến)
Tại thấy thớt có vẻ mới sử dung Dic cộng thêm bài 1, 2, chủ thớt dùng Tem làm key nên viết theo để chủ thớt dễ đoán vậy thôi bác.
 
Upvote 0
Thấy mọi người thường ... dùng Tem để gọi một cái biến mà họ không muốn đặt tên nghiêm chỉnh.
Thực tế, nó chỉ là một cái biến. Về tính chất "tạm bợ/temporary" nó không hẳn đạt yêu cầu. Tại sao không gọi thẳng là key cho đúng theo nhiệm vụ của nó. Hoặc là var (variable/biến)
Ý anh là đặt là key luôn ? Để em viết thử, có đợt em viết như vậy rồi nhưng không hiểu sao không chạy. Sẵn code mẫu của anh ChanhTQ ngày xưa viết cho nên em tùy biến luôn (vậy mà cũng phải loay hoay mãi mới xong)
 
Upvote 0
Ý anh là đặt là key luôn ? Để em viết thử, có đợt em viết như vậy rồi nhưng không hiểu sao không chạy. Sẵn code mẫu của anh ChanhTQ ngày xưa viết cho nên em tùy biến luôn (vậy mà cũng phải loay hoay mãi mới xong)
Bon với chen một tí nha, thấy đáp số sao làm vậy thôi nha, tùy chỉnh lại cái sub main là ok
Mã:
Sub NapDic(Dic As Object)
Dim i As Long
Dim J As Long
Dim Dcuoi As Long
Dim Arr_N()
Dcuoi = Sheet2.Range("A100000").End(xlUp).Row
Arr_N = Sheet2.Range("A6:K" & Dcuoi)
For J = 2 To UBound(Arr_N, 2)
    If Arr_N(1, J) <> "" Then
        For i = 2 To UBound(Arr_N, 1)
          If Not Dic.exists(Arr_N(i, 1) & "-" & Arr_N(1, J)) Then
              Dic.Add Arr_N(i, 1) & "-" & Arr_N(1, J), Arr_N(i, J)
           End If
        Next
    End If
Next
End Sub
Mã:
Sub main()
Dim i As Long
Dim J As Long
Dim Dic As Object
Set Dic = CreateObject("scripting.dictionary")
Call NapDic(Dic)
For i = 3 To 8
    For J = 2 To 8
        If Dic.exists(Sheet1.Cells(i, 1) & "-" & Sheet1.Cells(2, J)) Then
            Cells(i, J) = Dic.Item(Sheet1.Cells(i, 1) & "-" & Sheet1.Cells(2, J))
        End If
    Next
Next
End Sub
 

File đính kèm

Upvote 0
Mình làm cái này để check số liệu với người khác. Số liệu đó ID thay đổi lúc vị trí dòng này lúc dòng khác nên dùng dic để xác định dòng, còn cột tùy vào công việc mình cần thay đổi cột nọ cột kia nên dùng thêm Dic để xác định cột thông qua code cột. Theo bạn có phương án nào khả thi hơn???
Nếu cột A ở Sheet "TH" là duy nhất & dữ liệu không nhiều thì dùng Dic trong bài này khó hiểu quá. Nếu chỉ là để tập viết với em "Đít- to" thì không bàn, còn nếu dùng Dic để xác định dòng & cột trong trường hợp này thì có vẻ .....hơi rối & hơi phí. Híc
Thân
 
Upvote 0
Nếu cột A ở Sheet "TH" là duy nhất & dữ liệu không nhiều thì dùng Dic trong bài này khó hiểu quá. Nếu chỉ là để tập viết với em "Đít- to" thì không bàn, còn nếu dùng Dic để xác định dòng & cột trong trường hợp này thì có vẻ .....hơi rối & hơi phí. Híc
Thân
Anh ơi vậy anh thử viết theo một cách khác cho em xem được không? Dữ liệu nguồn và dữ liệu đích của cái cột A nó lung tung chứ ko theo đúng thứ tự và có thể bên có bên không.
Bài đã được tự động gộp:

Bon với chen một tí nha, thấy đáp số sao làm vậy thôi nha, tùy chỉnh lại cái sub main là ok
Mã:
Sub NapDic(Dic As Object)
Dim i As Long
Dim J As Long
Dim Dcuoi As Long
Dim Arr_N()
Dcuoi = Sheet2.Range("A100000").End(xlUp).Row
Arr_N = Sheet2.Range("A6:K" & Dcuoi)
For J = 2 To UBound(Arr_N, 2)
    If Arr_N(1, J) <> "" Then
        For i = 2 To UBound(Arr_N, 1)
          If Not Dic.exists(Arr_N(i, 1) & "-" & Arr_N(1, J)) Then
              Dic.Add Arr_N(i, 1) & "-" & Arr_N(1, J), Arr_N(i, J)
           End If
        Next
    End If
Next
End Sub
Mã:
Sub main()
Dim i As Long
Dim J As Long
Dim Dic As Object
Set Dic = CreateObject("scripting.dictionary")
Call NapDic(Dic)
For i = 3 To 8
    For J = 2 To 8
        If Dic.exists(Sheet1.Cells(i, 1) & "-" & Sheet1.Cells(2, J)) Then
            Cells(i, J) = Dic.Item(Sheet1.Cells(i, 1) & "-" & Sheet1.Cells(2, J))
        End If
    Next
Next
End Sub
Cho em hỏi sao gọi là sub main? Để có thể tùy biến đúng không anh? Vì em thấy trong này bản chất nó là tách một đoạn code trong một code hoàn chỉnh.
 
Lần chỉnh sửa cuối:
Upvote 0
Anh ơi vậy anh thử viết theo một cách khác cho em xem được không? Dữ liệu nguồn và dữ liệu đích của cái cột A nó lung tung chứ ko theo đúng thứ tự và có thể bên có bên không.
Bài đã được tự động gộp:


Cho em hỏi sao gọi là sub main? Để có thể tùy biến đúng không anh? Vì em thấy trong này bản chất nó là tách một đoạn code trong một code hoàn chỉnh.
cái này là viết 2 chương trình con rồi khi nào chạy thì mình gọi vào thôi bạn à.theo mình hiểu là vậy
 
Upvote 0
Anh ơi vậy anh thử viết theo một cách khác cho em xem được không? Dữ liệu nguồn và dữ liệu đích của cái cột A nó lung tung chứ ko theo đúng thứ tự và có thể bên có bên không.
Có thể mình hiểu chưa đúng, thử em này:
Mã:
Public Sub NgoWa()
    Dim Vung, Cot, Wf, I, J, Kq, CotKq, Chay, iHang
    Set Vung = Sheets("TH").Range(Sheets("TH").[A7], Sheets("TH").[A5000].End(xlUp)).Resize(, 11)
    Set Wf = Application.WorksheetFunction
    Set Cot = Sheets("TH").[B6].Resize(, Vung.Columns.Count - 1)
    CotKq = Range([B2], [W2].End(xlToLeft))
    ReDim Chay(1 To UBound(CotKq, 2))
    Kq = Sheets("KQ").Range(Sheets("KQ").[A3], Sheets("KQ").[A5000].End(xlUp)).Resize(, UBound(CotKq, 2) + 1)
        For I = 1 To UBound(CotKq, 2)
            If CotKq(1, I) <> "" Then Chay(I) = Wf.Match(CotKq(1, I), Cot, 0)
        Next I
            For I = 1 To UBound(Kq)
                If Wf.CountIf(Vung.Columns(1), Kq(I, 1)) Then
                    iHang = Wf.Match(Kq(I, 1), Vung.Columns(1), 0)
                    For J = 2 To UBound(Chay) + 1
                        If Chay(J - 1) = "" Then
                            Kq(I, J) = ""
                        Else
                            Kq(I, J) = Vung(iHang, Chay(J - 1) + 1)
                        End If
                    Next J
                 End If
            Next I
    [A3:I1000].ClearContents
    [A3].Resize(UBound(Kq), UBound(Kq, 2)) = Kq
End Sub
Thân
 

File đính kèm

Upvote 0
Có thể mình hiểu chưa đúng, thử em này:
Mã:
Public Sub NgoWa()
    Dim Vung, Cot, Wf, I, J, Kq, CotKq, Chay, iHang
    Set Vung = Sheets("TH").Range(Sheets("TH").[A7], Sheets("TH").[A5000].End(xlUp)).Resize(, 11)
    Set Wf = Application.WorksheetFunction
    Set Cot = Sheets("TH").[B6].Resize(, Vung.Columns.Count - 1)
    CotKq = Range([B2], [W2].End(xlToLeft))
    ReDim Chay(1 To UBound(CotKq, 2))
    Kq = Sheets("KQ").Range(Sheets("KQ").[A3], Sheets("KQ").[A5000].End(xlUp)).Resize(, UBound(CotKq, 2) + 1)
        For I = 1 To UBound(CotKq, 2)
            If CotKq(1, I) <> "" Then Chay(I) = Wf.Match(CotKq(1, I), Cot, 0)
        Next I
            For I = 1 To UBound(Kq)
                If Wf.CountIf(Vung.Columns(1), Kq(I, 1)) Then
                    iHang = Wf.Match(Kq(I, 1), Vung.Columns(1), 0)
                    For J = 2 To UBound(Chay) + 1
                        If Chay(J - 1) = "" Then
                            Kq(I, J) = ""
                        Else
                            Kq(I, J) = Vung(iHang, Chay(J - 1) + 1)
                        End If
                    Next J
                 End If
            Next I
    [A3:I1000].ClearContents
    [A3].Resize(UBound(Kq), UBound(Kq, 2)) = Kq
End Sub
Thân

Kết quả như em mong muốn rồi anh ạ, nhưng về tốc độ thì không bằng Dic được. Thật sự thì em thích sử dụng Dic vì nó mạnh :D
Bài đã được tự động gộp:

Bon với chen một tí nha, thấy đáp số sao làm vậy thôi nha, tùy chỉnh lại cái sub main là ok
Mã:
Sub NapDic(Dic As Object)
Dim i As Long
Dim J As Long
Dim Dcuoi As Long
Dim Arr_N()
Dcuoi = Sheet2.Range("A100000").End(xlUp).Row
Arr_N = Sheet2.Range("A6:K" & Dcuoi)
For J = 2 To UBound(Arr_N, 2)
    If Arr_N(1, J) <> "" Then
        For i = 2 To UBound(Arr_N, 1)
          If Not Dic.exists(Arr_N(i, 1) & "-" & Arr_N(1, J)) Then
              Dic.Add Arr_N(i, 1) & "-" & Arr_N(1, J), Arr_N(i, J)
           End If
        Next
    End If
Next
End Sub
Mã:
Sub main()
Dim i As Long
Dim J As Long
Dim Dic As Object
Set Dic = CreateObject("scripting.dictionary")
Call NapDic(Dic)
For i = 3 To 8
    For J = 2 To 8
        If Dic.exists(Sheet1.Cells(i, 1) & "-" & Sheet1.Cells(2, J)) Then
            Cells(i, J) = Dic.Item(Sheet1.Cells(i, 1) & "-" & Sheet1.Cells(2, J))
        End If
    Next
Next
End Sub
À trường hợp này không an toàn vì có thể việc kết hợp giữa dòng và cột làm key chưa chắc chắn. Ví dụ một ID là 10 và cột là 19 với một ID là 101 và cột là 9.
 
Lần chỉnh sửa cuối:
Upvote 0
Kết quả như em mong muốn rồi anh ạ, nhưng về tốc độ thì không bằng Dic được. Thật sự thì em thích sử dụng Dic vì nó mạnh :D
Bài đã được tự động gộp:


À trường hợp này không an toàn vì có thể việc kết hợp giữa dòng và cột làm key chưa chắc chắn. Ví dụ một ID là 10 và cột là 19 với một ID là 101 và cột là 9.
bạn cho tôi biết trường hợp nào không an toàn đi nha, để tôi học hỏi thêm, cho ví dụ cụ thể trên file luôn để mọi người học hỏi nha
 
Upvote 0
Web KT

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

Back
Top Bottom