Nhờ viết code VBA thay thế các hàm thống kê để xử lý bảng tính được nhanh hơn

Liên hệ QC

Tuan_hcth

Thành viên thường trực
Tham gia
8/4/07
Bài viết
206
Được thích
11
Qua sự giúp đỡ của các anh chị trên diễn đàn về các công thức thống kê như countif, countifs, các hàm dạng mảng như sumproduct, FREQUENCY... em đã có thể áp dụng để thực hiện công việc của mình. Tuy nhiên, khi áp dụng với số lượng dữ liệu lớn, file excel chạy rất chậm, thậm chí còn bị treo. Vì vậy, em gửi file lên đây nhờ anh, chị xử lý bằng VBA giúp em với ạ. Trong file Thong ke, cần thống kê theo điều kiện tại từng cột căn cứ vào dữ liệu ở file Data. Rất mong các anh, chị giúp đỡ. Em xin cảm ơn nhiều ạ.
 

File đính kèm

Bạn chạy đoạn code dưới đây.
Mã:
Sub Tonghop()
Dim Solieu As Variant
Dim DK1(1 To 3) As Variant
Dim DK2(1 To 2) As Variant
Dim GHP As String
Dim MNG, GH
Dim KQ As Variant
Dim i As Long
Dim DicTH As Object
Set DicTH = CreateObject("Scripting.Dictionary")
Solieu = Sheet1.Range("a4", Sheet1.Range("d4").End(xlDown))
GH = 16 / 8 / 2018
For i = 1 To UBound(Solieu)
    If Solieu(i, 4) >= GH Then
        DK1(1) = Solieu(i, 2)
        DK1(2) = Solieu(i, 3)
        DK1(3) = Solieu(i, 1)
        DK2(1) = Solieu(i, 2)
        DK2(2) = Solieu(i, 3)
        GHP = Join(DK1)
        If DicTH.Exists(GHP) = False Then
            DicTH(GHP) = Array(DK1, 1)
        Else
            MNG = DicTH(GHP)
            MNG(1) = MNG(1) + 1
            DicTH(GHP) = MNG
        End If
        GHP = Join(DK2)
        DicTH(GHP) = DicTH(GHP) + 1
    End If
Next i
ReDim KQ(1 To 8, 1 To 9)
KQ(1, 1) = "Don vi": KQ(1, 2) = "$": KQ(1, 3) = "@": KQ(1, 4) = "Nhan vien ban mat hang $ > 5"
KQ(1, 5) = "Nhan vien ban mat hang @ > 5": KQ(1, 6) = "Nhan vien ban mat hang $ < 3"
KQ(1, 7) = "Nhan vien ban mat hang @ < 3": KQ(1, 8) = "Nhan vien ban mat hang $ 3 <= SL <= 5"
KQ(1, 9) = "Nhan vien ban mat hang @ 3 <= Sl <= 5"
For i = 2 To 8
    KQ(i, 1) = i - 1
Next i
For i = 2 To UBound(KQ)
    GHP = KQ(i, 1) & " " & "$"
    KQ(i, 2) = DicTH(GHP)
    DicTH.Remove GHP
    GHP = KQ(i, 1) & " " & "@"
    KQ(i, 3) = DicTH(GHP)
    DicTH.Remove GHP
Next i
For i = 2 To UBound(KQ)
    For Each MNG In DicTH.Keys
        If DicTH(MNG)(0)(1) = KQ(i, 1) Then
            If DicTH(MNG)(0)(2) = "$" Then
                If DicTH(MNG)(1) > 5 Then
                    'KQ(i, 4) = KQ(i, 4) & " " & DicTH(MNG)(0)(3)
                    KQ(i, 4) = KQ(i, 4) + 1
                    DicTH.Remove MNG
                Else
                    If DicTH(MNG)(1) < 3 Then
                        'KQ(i, 6) = KQ(i, 6) & " " & DicTH(MNG)(0)(3)
                        KQ(i, 6) = KQ(i, 6) + 1
                        DicTH.Remove MNG
                    Else
                        'KQ(i, 8) = KQ(i, 8) & " " & DicTH(MNG)(0)(3)
                        KQ(i, 8) = KQ(i, 8) + 1
                        DicTH.Remove MNG
                    End If
                End If
            Else
                If DicTH(MNG)(1) > 5 Then
                    'KQ(i, 5) = KQ(i, 5) & " " & DicTH(MNG)(0)(3)
                    KQ(i, 5) = KQ(i, 5) + 1
                    DicTH.Remove MNG
                Else
                    If DicTH(MNG)(1) < 3 Then
                        'KQ(i, 7) = KQ(i, 7) & " " & DicTH(MNG)(0)(3)
                        KQ(i, 7) = KQ(i, 7) + 1
                        DicTH.Remove MNG
                    Else
                        'KQ(i, 9) = KQ(i, 9) & " " & DicTH(MNG)(0)(3)
                        KQ(i, 9) = KQ(i, 9) + 1
                        DicTH.Remove MNG
                    End If
                End If
            End If
        End If
    Next MNG
Next i
With Sheet2
.UsedRange.ClearContents
.Range("a3").Resize(UBound(KQ), UBound(KQ, 2)) = KQ
.Range("a3").Resize(UBound(KQ), UBound(KQ, 2)).Borders.LineStyle = 1
.UsedRange.Columns.AutoFit
End With
End Sub
Nhờ bác giải thích giúp em đoạn code này vơí ạ:
For i = 2 To UBound(KQ)
For Each MNG In DicTH.Keys
If DicTH(MNG)(0)(1) = KQ(i, 1) Then
If DicTH(MNG)(0)(2) = "$" Then
If DicTH(MNG)(1) > 5 Then
'KQ(i, 4) = KQ(i, 4) & " " & DicTH(MNG)(0)(3)
KQ(i, 4) = KQ(i, 4) + 1
DicTH.Remove MNG
 
Upvote 0
Nhờ bác giải thích giúp em đoạn code này vơí ạ:
For i = 2 To UBound(KQ)
For Each MNG In DicTH.Keys
If DicTH(MNG)(0)(1) = KQ(i, 1) Then
If DicTH(MNG)(0)(2) = "$" Then
If DicTH(MNG)(1) > 5 Then
'KQ(i, 4) = KQ(i, 4) & " " & DicTH(MNG)(0)(3)
KQ(i, 4) = KQ(i, 4) + 1
DicTH.Remove MNG
Đoạn này là so sánh item cua key voi cac điều kiện tổng hợp, cái nào khớp thì lấy ra.
Code thì vậy nhưng giải thích hơi không quen, bạn tìm hiểu đi vậy.
 
Upvote 0
Bạn chạy đoạn code dưới đây.
Mã:
Sub Tonghop()
Dim Solieu As Variant
Dim DK1(1 To 3) As Variant
Dim DK2(1 To 2) As Variant
Dim GHP As String
Dim MNG, GH
Dim KQ As Variant
Dim i As Long
Dim DicTH As Object
Set DicTH = CreateObject("Scripting.Dictionary")
Solieu = Sheet1.Range("a4", Sheet1.Range("d4").End(xlDown))
GH = 16 / 8 / 2018
For i = 1 To UBound(Solieu)
    If Solieu(i, 4) >= GH Then
        DK1(1) = Solieu(i, 2)
        DK1(2) = Solieu(i, 3)
        DK1(3) = Solieu(i, 1)
        DK2(1) = Solieu(i, 2)
        DK2(2) = Solieu(i, 3)
        GHP = Join(DK1)
        If DicTH.Exists(GHP) = False Then
            DicTH(GHP) = Array(DK1, 1)
        Else
            MNG = DicTH(GHP)
            MNG(1) = MNG(1) + 1
            DicTH(GHP) = MNG
        End If
        GHP = Join(DK2)
        DicTH(GHP) = DicTH(GHP) + 1
    End If
Next i
ReDim KQ(1 To 8, 1 To 9)
KQ(1, 1) = "Don vi": KQ(1, 2) = "$": KQ(1, 3) = "@": KQ(1, 4) = "Nhan vien ban mat hang $ > 5"
KQ(1, 5) = "Nhan vien ban mat hang @ > 5": KQ(1, 6) = "Nhan vien ban mat hang $ < 3"
KQ(1, 7) = "Nhan vien ban mat hang @ < 3": KQ(1, 8) = "Nhan vien ban mat hang $ 3 <= SL <= 5"
KQ(1, 9) = "Nhan vien ban mat hang @ 3 <= Sl <= 5"
For i = 2 To 8
    KQ(i, 1) = i - 1
Next i
For i = 2 To UBound(KQ)
    GHP = KQ(i, 1) & " " & "$"
    KQ(i, 2) = DicTH(GHP)
    DicTH.Remove GHP
    GHP = KQ(i, 1) & " " & "@"
    KQ(i, 3) = DicTH(GHP)
    DicTH.Remove GHP
Next i
For i = 2 To UBound(KQ)
    For Each MNG In DicTH.Keys
        If DicTH(MNG)(0)(1) = KQ(i, 1) Then
            If DicTH(MNG)(0)(2) = "$" Then
                If DicTH(MNG)(1) > 5 Then
                    'KQ(i, 4) = KQ(i, 4) & " " & DicTH(MNG)(0)(3)
                    KQ(i, 4) = KQ(i, 4) + 1
                    DicTH.Remove MNG
                Else
                    If DicTH(MNG)(1) < 3 Then
                        'KQ(i, 6) = KQ(i, 6) & " " & DicTH(MNG)(0)(3)
                        KQ(i, 6) = KQ(i, 6) + 1
                        DicTH.Remove MNG
                    Else
                        'KQ(i, 8) = KQ(i, 8) & " " & DicTH(MNG)(0)(3)
                        KQ(i, 8) = KQ(i, 8) + 1
                        DicTH.Remove MNG
                    End If
                End If
            Else
                If DicTH(MNG)(1) > 5 Then
                    'KQ(i, 5) = KQ(i, 5) & " " & DicTH(MNG)(0)(3)
                    KQ(i, 5) = KQ(i, 5) + 1
                    DicTH.Remove MNG
                Else
                    If DicTH(MNG)(1) < 3 Then
                        'KQ(i, 7) = KQ(i, 7) & " " & DicTH(MNG)(0)(3)
                        KQ(i, 7) = KQ(i, 7) + 1
                        DicTH.Remove MNG
                    Else
                        'KQ(i, 9) = KQ(i, 9) & " " & DicTH(MNG)(0)(3)
                        KQ(i, 9) = KQ(i, 9) + 1
                        DicTH.Remove MNG
                    End If
                End If
            End If
        End If
    Next MNG
Next i
With Sheet2
.UsedRange.ClearContents
.Range("a3").Resize(UBound(KQ), UBound(KQ, 2)) = KQ
.Range("a3").Resize(UBound(KQ), UBound(KQ, 2)).Borders.LineStyle = 1
.UsedRange.Columns.AutoFit
End With
End Sub
Kết quả chạy ra chưa chính xác bác ạ. Em gửi file nhờ bác kiểm tra giúp: tại sheet2, vùng bôi màu vàng là vùng chạy bằng code VBA, còn phần kết quả bên dưới vùng màu vàng là cách tính thủ công.
 

File đính kèm

Upvote 0
file của bạn số liệu trong tháng 8 sửa nhanh thê này
Thêm dấu ' trước câu lệnh
Mã:
If Solieu(i, 4) >= GH Then
thành
'If Solieu(i, 4) >= GH Then
Thêm câu lệnh này vào dòng bên dưới
Mã:
If Day(Solieu(i, 4)) >= 16 Then
Đơn vị số 2 & 7 bạn thống kê bị lỗi.
Nếu số liệu trong nhiều tháng, năm, sẽ cần sửa điều kiện so sánh ( GH )
 
Lần chỉnh sửa cuối:
Upvote 0
file của bạn số liệu trong tháng 8 sửa nhanh thê này
Thêm dấu ' trước câu lệnh
Mã:
If Solieu(i, 4) >= GH Then
thành
'If Solieu(i, 4) >= GH Then
Thêm câu lệnh này vào dòng bên dưới
Mã:
If Day(Solieu(i, 4)) >= 16 Then
Đơn vị số 2 & 7 bạn thống kê bị lỗi.
Nếu số liệu trong nhiều tháng, năm, sẽ cần sửa điều kiện so sánh ( GH )
Em đổ dữ liệu vào để chạy nhưng nó báo lỗi đoạn GHP = Join(DK1). Nhờ bác kiểm tra file giúp em với ạ.
 

File đính kèm

Upvote 0
Là do tên đơn vị theo mẫu chỉ đến 7, file thực của bạn đến 19 nên thiếu dòng của bang kết quả. Cái này sửa nhanh thôi.
Trong tên đơn vị có cả #N/A dòng 20786 có đưa vao tính hay không?
 
Upvote 0
Đến 26 bài rồi vẫn còn hỏi đề bài?
 
Upvote 0
Là do tên đơn vị theo mẫu chỉ đến 7, file thực của bạn đến 19 nên thiếu dòng của bang kết quả. Cái này sửa nhanh thôi.
Trong tên đơn vị có cả #N/A dòng 20786 có đưa vao tính hay không?
Cảm ơn bác. Tên đơn vị nếu có ô là #N/A thì bác xóa và coi như là ô trống. Viết code thế nào để khi chạy nó bỏ qua những ô này không tính là được ạ.
 
Upvote 0
Cảm ơn bác. Tên đơn vị nếu có ô là #N/A thì bác xóa và coi như là ô trống. Viết code thế nào để khi chạy nó bỏ qua những ô này không tính là được ạ.
Ngày tháng giới hạn lọc bạn thay đổi tại dòng bôi đậm
Gặp dòng lỗi là loại, không thống kê
Mã:
Sub Tonghop()
Dim Solieu As Variant
Dim DK1(1 To 3) As Variant
Dim DK2(1 To 2) As Variant
Dim GHP As String
Dim MNG, GH
Dim KQ As Variant
Dim i As Long, Max_
Dim DicTH As Object
Set DicTH = CreateObject("Scripting.Dictionary")
Solieu = Sheet1.Range("a4", Sheet1.Range("d4").End(xlDown))
GH = DateSerial(2018, 8, 16) 'Thay doi gioi han loc tai day
For i = 1 To UBound(Solieu)
    If Solieu(i, 4) >= GH Then
        If IsError(Solieu(i, 2)) = False Then 'Loai tru loi tai dong nay
            If Max_ < Solieu(i, 2) Then Max_ = Solieu(i, 2)
            DK1(1) = Solieu(i, 2)
            DK1(2) = Solieu(i, 3)
            DK1(3) = Solieu(i, 1)
            DK2(1) = Solieu(i, 2)
            DK2(2) = Solieu(i, 3)
            GHP = Join(DK1)
            If DicTH.Exists(GHP) = False Then
                DicTH(GHP) = Array(DK1, 1)
            Else
                MNG = DicTH(GHP)
                MNG(1) = MNG(1) + 1
                DicTH(GHP) = MNG
            End If
            GHP = Join(DK2)
            DicTH(GHP) = DicTH(GHP) + 1
        End If
    End If
Next i
ReDim KQ(1 To Max_ + 1, 1 To 9)
KQ(1, 1) = "Don vi": KQ(1, 2) = "$": KQ(1, 3) = "@": KQ(1, 4) = "Nhan vien ban mat hang $ > 5"
KQ(1, 5) = "Nhan vien ban mat hang @ > 5": KQ(1, 6) = "Nhan vien ban mat hang $ < 3"
KQ(1, 7) = "Nhan vien ban mat hang @ < 3": KQ(1, 8) = "Nhan vien ban mat hang $ 3 <= SL <= 5"
KQ(1, 9) = "Nhan vien ban mat hang @ 3 <= Sl <= 5"
For i = 2 To Max_ + 1
    KQ(i, 1) = i - 1
Next i
For i = 2 To UBound(KQ)
    GHP = KQ(i, 1) & " " & "$"
    KQ(i, 2) = DicTH(GHP)
    DicTH.Remove GHP
    GHP = KQ(i, 1) & " " & "@"
    KQ(i, 3) = DicTH(GHP)
    DicTH.Remove GHP
Next i
For i = 2 To UBound(KQ)
    For Each MNG In DicTH.Keys
        If DicTH(MNG)(0)(1) = KQ(i, 1) Then
            If DicTH(MNG)(0)(2) = "$" Then
                If DicTH(MNG)(1) > 5 Then
                    'KQ(i, 4) = KQ(i, 4) & " " & DicTH(MNG)(0)(3)
                    KQ(i, 4) = KQ(i, 4) + 1
                    DicTH.Remove MNG
                Else
                    If DicTH(MNG)(1) < 3 Then
                        'KQ(i, 6) = KQ(i, 6) & " " & DicTH(MNG)(0)(3)
                        KQ(i, 6) = KQ(i, 6) + 1
                        DicTH.Remove MNG
                    Else
                        'KQ(i, 8) = KQ(i, 8) & " " & DicTH(MNG)(0)(3)
                        KQ(i, 8) = KQ(i, 8) + 1
                        DicTH.Remove MNG
                    End If
                End If
            Else
                If DicTH(MNG)(1) > 5 Then
                    'KQ(i, 5) = KQ(i, 5) & " " & DicTH(MNG)(0)(3)
                    KQ(i, 5) = KQ(i, 5) + 1
                    DicTH.Remove MNG
                Else
                    If DicTH(MNG)(1) < 3 Then
                        'KQ(i, 7) = KQ(i, 7) & " " & DicTH(MNG)(0)(3)
                        KQ(i, 7) = KQ(i, 7) + 1
                        DicTH.Remove MNG
                    Else
                        'KQ(i, 9) = KQ(i, 9) & " " & DicTH(MNG)(0)(3)
                        KQ(i, 9) = KQ(i, 9) + 1
                        DicTH.Remove MNG
                    End If
                End If
            End If
        End If
    Next MNG
Next i
With Sheet2
.UsedRange.ClearContents
.Range("a3").Resize(UBound(KQ), UBound(KQ, 2)) = KQ
.Range("a3").Resize(UBound(KQ), UBound(KQ, 2)).Borders.LineStyle = 1
.UsedRange.Columns.AutoFit
End With
End Sub
 
Upvote 0
Ngày tháng giới hạn lọc bạn thay đổi tại dòng bôi đậm
Gặp dòng lỗi là loại, không thống kê
Mã:
Sub Tonghop()
Dim Solieu As Variant
Dim DK1(1 To 3) As Variant
Dim DK2(1 To 2) As Variant
Dim GHP As String
Dim MNG, GH
Dim KQ As Variant
Dim i As Long, Max_
Dim DicTH As Object
Set DicTH = CreateObject("Scripting.Dictionary")
Solieu = Sheet1.Range("a4", Sheet1.Range("d4").End(xlDown))
GH = DateSerial(2018, 8, 16) 'Thay doi gioi han loc tai day
For i = 1 To UBound(Solieu)
    If Solieu(i, 4) >= GH Then
        If IsError(Solieu(i, 2)) = False Then 'Loai tru loi tai dong nay
            If Max_ < Solieu(i, 2) Then Max_ = Solieu(i, 2)
            DK1(1) = Solieu(i, 2)
            DK1(2) = Solieu(i, 3)
            DK1(3) = Solieu(i, 1)
            DK2(1) = Solieu(i, 2)
            DK2(2) = Solieu(i, 3)
            GHP = Join(DK1)
            If DicTH.Exists(GHP) = False Then
                DicTH(GHP) = Array(DK1, 1)
            Else
                MNG = DicTH(GHP)
                MNG(1) = MNG(1) + 1
                DicTH(GHP) = MNG
            End If
            GHP = Join(DK2)
            DicTH(GHP) = DicTH(GHP) + 1
        End If
    End If
Next i
ReDim KQ(1 To Max_ + 1, 1 To 9)
KQ(1, 1) = "Don vi": KQ(1, 2) = "$": KQ(1, 3) = "@": KQ(1, 4) = "Nhan vien ban mat hang $ > 5"
KQ(1, 5) = "Nhan vien ban mat hang @ > 5": KQ(1, 6) = "Nhan vien ban mat hang $ < 3"
KQ(1, 7) = "Nhan vien ban mat hang @ < 3": KQ(1, 8) = "Nhan vien ban mat hang $ 3 <= SL <= 5"
KQ(1, 9) = "Nhan vien ban mat hang @ 3 <= Sl <= 5"
For i = 2 To Max_ + 1
    KQ(i, 1) = i - 1
Next i
For i = 2 To UBound(KQ)
    GHP = KQ(i, 1) & " " & "$"
    KQ(i, 2) = DicTH(GHP)
    DicTH.Remove GHP
    GHP = KQ(i, 1) & " " & "@"
    KQ(i, 3) = DicTH(GHP)
    DicTH.Remove GHP
Next i
For i = 2 To UBound(KQ)
    For Each MNG In DicTH.Keys
        If DicTH(MNG)(0)(1) = KQ(i, 1) Then
            If DicTH(MNG)(0)(2) = "$" Then
                If DicTH(MNG)(1) > 5 Then
                    'KQ(i, 4) = KQ(i, 4) & " " & DicTH(MNG)(0)(3)
                    KQ(i, 4) = KQ(i, 4) + 1
                    DicTH.Remove MNG
                Else
                    If DicTH(MNG)(1) < 3 Then
                        'KQ(i, 6) = KQ(i, 6) & " " & DicTH(MNG)(0)(3)
                        KQ(i, 6) = KQ(i, 6) + 1
                        DicTH.Remove MNG
                    Else
                        'KQ(i, 8) = KQ(i, 8) & " " & DicTH(MNG)(0)(3)
                        KQ(i, 8) = KQ(i, 8) + 1
                        DicTH.Remove MNG
                    End If
                End If
            Else
                If DicTH(MNG)(1) > 5 Then
                    'KQ(i, 5) = KQ(i, 5) & " " & DicTH(MNG)(0)(3)
                    KQ(i, 5) = KQ(i, 5) + 1
                    DicTH.Remove MNG
                Else
                    If DicTH(MNG)(1) < 3 Then
                        'KQ(i, 7) = KQ(i, 7) & " " & DicTH(MNG)(0)(3)
                        KQ(i, 7) = KQ(i, 7) + 1
                        DicTH.Remove MNG
                    Else
                        'KQ(i, 9) = KQ(i, 9) & " " & DicTH(MNG)(0)(3)
                        KQ(i, 9) = KQ(i, 9) + 1
                        DicTH.Remove MNG
                    End If
                End If
            End If
        End If
    Next MNG
Next i
With Sheet2
.UsedRange.ClearContents
.Range("a3").Resize(UBound(KQ), UBound(KQ, 2)) = KQ
.Range("a3").Resize(UBound(KQ), UBound(KQ, 2)).Borders.LineStyle = 1
.UsedRange.Columns.AutoFit
End With
End Sub
Cảm ơn bác đã nhiệt tình giúp đỡ. Giờ em thay đổi dữ liệu mặt hàng thì khi chạy nó báo lỗi. Em đã có chỉnh sửa một số đoạn code khi thay đổi dữ liệu (theo suy nghĩ của em). Em gửi file nhờ bác kiểm tra giúp em với ạ.
 

File đính kèm

Upvote 0
Web KT

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

Back
Top Bottom