Nhờ viết code lấy trung bình cộng

Liên hệ QC

SoGoKu7

Thành viên chính thức
Tham gia
4/9/21
Bài viết
62
Được thích
13
Giới tính
Nữ
Em chào anh/chị
Em có dữ liệu cần tổng hợp theo dạng cộng dồn số lượng nếu trùng mã sản phẩm, các hạng mục còn lại thì lấy trung bình cộng.
Em biết nếu dữ liệu chuẩn như phía dưới thì dùng pivot sẽ rất nhanh, nhưng dữ liệu gốc còn nhiều điều kiện ràng buộc khác nên rất mong anh/chị code dùm em nhé!
Xin cảm ơn anh chị nhiều ạ!
1668917129198.png
 

File đính kèm

  • GPE2011.xlsx
    9.5 KB · Đọc: 13
Dữ liệu thế này thì dùng công thức cơ bản là ra rồi cần gì code hả bạn?
Dạ đây chỉ là file giả định anh ạ, dữ liệu em cũng không lớn lắm, khoảng 5 trăm dòng thôi nhưng nó ràng buộc nhiều điều kiện nên em đang nhờ anh chị code, em có dùng dictionảy nhưng chỉ được cột tổng thôi. Các cột tính trung bình em chưa biết logic sao nữa.
Nhờ anh chị giúp đỡ ạ!
 
Upvote 0
Em chào anh/chị
Em có dữ liệu cần tổng hợp theo dạng cộng dồn số lượng nếu trùng mã sản phẩm, các hạng mục còn lại thì lấy trung bình cộng.
Em biết nếu dữ liệu chuẩn như phía dưới thì dùng pivot sẽ rất nhanh, nhưng dữ liệu gốc còn nhiều điều kiện ràng buộc khác nên rất mong anh/chị code dùm em nhé!
Xin cảm ơn anh chị nhiều ạ!
View attachment 283627
Lâu lâu không viết có vẻ ngượng tay.
Bạn tham khảo nhé!
PHP:
Option Explicit

Sub PivotByDictionary()
    Dim sArr(), Res(), Dic As Object, Header As Range
    Dim I As Long, R As Long, Col As Integer, nCol As Integer
    Dim K As Long, lR As Long
   
    'Tat nhay man hinh
    Application.ScreenUpdating = False
    'Khai bao thu vien Dictionary
    Set Dic = CreateObject("Scripting.Dictionary")
    'Dong tieu de
    Set Header = Sheet1.Range("B5:F5")
    'Dong cuoi cung co du lieu
    lR = Sheet1.Range("B" & Rows.Count).End(xlUp).Row
    'Mang 2 chieu chua toan bo du lieu
    sArr() = Sheet1.Range("B6:F" & lR).Value
    'Can tren cua chieu thu nhat mang sArr
    R = UBound(sArr, 1)
    'Quy dinh kich thuoc mang ket qua Res
    ReDim Res(1 To R, 1 To UBound(sArr, 2) + 1)
    'Can tren cua chieu thu hai mang Res
    Col = UBound(Res, 2)
     
    'Chay vong lap qua tung dong du lieu cua mang sArr
    For I = 1 To R
        'Kiem tra Ma san pham da ton tai trong Dictionary chua
        If Not Dic.exists(sArr(I, 1)) Then
            K = K + 1   'Tang thu tu
            'Add ma san pham la Key vao Dic voi Item la thu tu
            Dic.Add sArr(I, 1), K
            'Chay vong lap qua tung cot de lay gia tri vao Res
            For nCol = 1 To Col - 1
                Res(K, nCol) = sArr(I, nCol)
            Next nCol
            'Cot cuoi cung de tinh so lan xuat hien cua tung Ma san pham
            Res(K, Col) = 1
        Else
            'Truong hop ma san pham da ton tai
            For nCol = 2 To Col - 1
                Res(Dic.item(sArr(I, 1)), nCol) = Res(Dic.item(sArr(I, 1)), nCol) + sArr(I, nCol)
            Next nCol
            'So lan xuat hien tang them 1 lan so voi cu
            Res(Dic.Item(sArr(I, 1)), Col) = Res(Dic.Item(sArr(I, 1)), Col) + 1
        End If
    Next I
   
    'Tinh trung binh cong
    For I = 1 To K
        For nCol = 3 To Col - 1
            Res(I, nCol) = Res(I, nCol) / Res(I, Col)
        Next nCol
    Next I
   
    'Copy dong tieu de
    Header.Copy Sheet1.Range("H12")
    'Gan ket qua tu mang Res vao bang tinh
    Sheet1.Range("H13").Resize(K, Col - 1) = Res
   
    'Giai phong bo nho
    Set Dic = Nothing
    Set Header = Nothing
   
    'Mo nhay man hinh
    Application.ScreenUpdating = False
    'Thong bao hoan thanh thu tuc
    MsgBox "Done", vbInformation, "Daily Excel"
End Sub
 
Lần chỉnh sửa cuối:
Upvote 0
Lâu lâu không viết có vẻ ngượng tay.
Bạn tham khảo nhé!
PHP:
Option Explicit

Sub PivotByDictionary()
    Dim sArr(), Res(), Dic As Object, Header As Range
    Dim I As Long, R As Long, Col As Integer, nCol As Integer
    Dim K As Long, lR As Long
  
    'Tat nhay man hinh
    Application.ScreenUpdating = False
    'Khai bao thu vien Dictionary
    Set Dic = CreateObject("Scripting.Dictionary")
    'Dong tieu de
    Set Header = Sheet1.Range("B5:F5")
    'Dong cuoi cung co du lieu
    lR = Sheet1.Range("B" & Rows.Count).End(xlUp).Row
    'Mang 2 chieu chua toan bo du lieu
    sArr() = Sheet1.Range("B6:F" & lR).Value
    'Can tren cua chieu thu nhat mang sArr
    R = UBound(sArr, 1)
    'Quy dinh kich thuoc mang ket qua Res
    ReDim Res(1 To R, 1 To UBound(sArr, 2) + 1)
    'Can tren cua chieu thu hai mang Res
    Col = UBound(Res, 2)
    
    'Chay vong lap qua tung dong du lieu cua mang sArr
    For I = 1 To R
        'Kiem tra Ma san pham da ton tai trong Dictionary chua
        If Not Dic.exists(sArr(I, 1)) Then
            K = K + 1   'Tang thu tu
            'Add ma san pham la Key vao Dic voi Item la thu tu
            Dic.Add sArr(I, 1), K
            'Chay vong lap qua tung cot de lay gia tri vao Res
            For nCol = 1 To Col - 1
                Res(K, nCol) = sArr(I, nCol)
            Next nCol
            'Cot cuoi cung de tinh so lan xuat hien cua tung Ma san pham
            Res(K, Col) = 1
        Else
            'Truong hop ma san pham da ton tai
            For nCol = 2 To Col - 1
                Res(Dic.item(sArr(I, 1)), nCol) = Res(Dic.item(sArr(I, 1)), nCol) + sArr(I, nCol)
            Next nCol
            'So lan xuat hien tang them 1 lan so voi cu
            Res(Dic.Item(sArr(I, 1)), Col) = Res(Dic.Item(sArr(I, 1)), Col) + 1
        End If
    Next I
  
    'Tinh trung binh cong
    For I = 1 To K
        For nCol = 3 To Col - 1
            Res(I, nCol) = Res(I, nCol) / Res(I, Col)
        Next nCol
    Next I
  
    'Copy dong tieu de
    Header.Copy Sheet1.Range("H12")
    'Gan ket qua tu mang Res vao bang tinh
    Sheet1.Range("H13").Resize(K, Col - 1) = Res
  
    'Giai phong bo nho
    Set Dic = Nothing
    Set Header = Nothing
  
    'Mo nhay man hinh
    Application.ScreenUpdating = False
    'Thong bao hoan thanh thu tuc
    MsgBox "Done", vbInformation, "Daily Excel"
End Sub
Em cảm ơn anh nhiều nhé!
chạy code ra kết quả đúng rồi anh.
 
Upvote 0
Dạ đây chỉ là file giả định anh ạ, dữ liệu em cũng không lớn lắm, khoảng 5 trăm dòng thôi nhưng nó ràng buộc nhiều điều kiện nên em đang nhờ anh chị code, em có dùng dictionảy nhưng chỉ được cột tổng thôi. Các cột tính trung bình em chưa biết logic sao nữa.
Nhờ anh chị giúp đỡ ạ!
Bạn thử code dưới xem sao
PHP:
Option Explicit
Sub GPE()
    Dim Arr(), Res(), i&, j&, k&
    Dim Dic As Object, Key$, Lr&
    Set Dic = CreateObject("Scripting.Dictionary")
    With Sheets("Sheet1")
        Lr = .Range("B" & Rows.Count).End(xlUp).Row
        Arr = .Range("B6:F" & Lr).Value
        ReDim Res(1 To UBound(Arr), 1 To 6)
        For i = 1 To UBound(Arr)
            Key = Arr(i, 1)
            If Not Dic.exists(Key) Then
                k = k + 1
                Dic.Add (Key), k
                Res(k, 1) = Key
                Res(k, 2) = Arr(i, 2)
                For j = 3 To 5
                    Res(k, j) = Arr(i, j)
                Next j
                Res(k, 6) = 1
            Else
                Res(Dic.Item(Key), 2) = Res(Dic.Item(Key), 2) + Arr(i, 2)
                For j = 3 To 5
                    Res(Dic.Item(Key), j) = Res(Dic.Item(Key), j) + Arr(i, j)
                Next j
                Res(Dic.Item(Key), 6) = Res(Dic.Item(Key), 6) + 1
            End If
        Next i
            For i = 1 To k
                For j = 3 To 5
                    Res(i, j) = Res(i, j) / Res(i, 6)
                Next j
            Next i
        If k Then
            .Range("H12:L1000").ClearContents
            .Range("H12").Resize(k, 5).Value = Res
        End If
    End With
    Set Dic = Nothing
    MsgBox "Done"
End Sub
 
Upvote 0
Bạn thử code dưới xem sao
PHP:
Option Explicit
Sub GPE()
    Dim Arr(), Res(), i&, j&, k&
    Dim Dic As Object, Key$, Lr&
    Set Dic = CreateObject("Scripting.Dictionary")
    With Sheets("Sheet1")
        Lr = .Range("B" & Rows.Count).End(xlUp).Row
        Arr = .Range("B6:F" & Lr).Value
        ReDim Res(1 To UBound(Arr), 1 To 6)
        For i = 1 To UBound(Arr)
            Key = Arr(i, 1)
            If Not Dic.exists(Key) Then
                k = k + 1
                Dic.Add (Key), k
                Res(k, 1) = Key
                Res(k, 2) = Arr(i, 2)
                For j = 3 To 5
                    Res(k, j) = Arr(i, j)
                Next j
                Res(k, 6) = 1
            Else
                Res(Dic.Item(Key), 2) = Res(Dic.Item(Key), 2) + Arr(i, 2)
                For j = 3 To 5
                    Res(Dic.Item(Key), j) = Res(Dic.Item(Key), j) + Arr(i, j)
                Next j
                Res(Dic.Item(Key), 6) = Res(Dic.Item(Key), 6) + 1
            End If
        Next i
            For i = 1 To k
                For j = 3 To 5
                    Res(i, j) = Res(i, j) / Res(i, 6)
                Next j
            Next i
        If k Then
            .Range("H12:L1000").ClearContents
            .Range("H12").Resize(k, 5).Value = Res
        End If
    End With
    Set Dic = Nothing
    MsgBox "Done"
End Sub
Dạ, cảm ơn anh ạ
Kết quả chạy code đúng rồi ạ!
 
Upvote 0
Dạ, cảm ơn anh ạ
Kết quả chạy code đúng rồi ạ!
Thêm cách khác tham khảo
Mã:
Option Explicit
Sub ABC()
    Dim Dic As Object, sArr(), Res(), i&, Key, S, K&, j&
    Set Dic = CreateObject("Scripting.dictionary")
    With Sheets("Sheet1")
        sArr = .Range("B5:F" & .Range("B" & Rows.Count).End(3).Row).Value
        ReDim Res(1 To UBound(sArr), 1 To 5)
        For i = 2 To UBound(sArr)
            Dic(sArr(i, 1)) = Dic(sArr(i, 1)) & "," & i
        Next
        For Each Key In Dic.keys
            K = K + 1
            Res(K, 1) = Key
            S = Split(Dic(Key), ",")
            For i = 1 To UBound(S)
                For j = 2 To UBound(sArr, 2)
                    Res(K, j) = Res(K, j) + sArr(--S(i), j)
                Next
            Next
            For j = 3 To UBound(sArr, 2)
                Res(K, j) = Res(K, j) / UBound(S)
            Next
        Next
        .Range("H13:L1000").ClearContents
        .Range("H13").Resize(K, 5).Value = Res
    End With
End Sub
 
Upvote 0
Nếu có ràng buộc thì nên nói ràng buộc là gì, còn nếu như dữ liệu bài này thì nó đúng chuẩn pivot table rồi. Không phải code làm gì
 

File đính kèm

  • GPE2011.xlsx
    13.4 KB · Đọc: 3
Upvote 0
Em chào anh/chị
Em có dữ liệu cần tổng hợp theo dạng cộng dồn số lượng nếu trùng mã sản phẩm, các hạng mục còn lại thì lấy trung bình cộng.
Em biết nếu dữ liệu chuẩn như phía dưới thì dùng pivot sẽ rất nhanh, nhưng dữ liệu gốc còn nhiều điều kiện ràng buộc khác nên rất mong anh/chị code dùm em nhé!
Xin cảm ơn anh chị nhiều ạ!
View attachment 283627
Bạn dùng thử code sau nhé:

Mã:
Sub TongHop_HLMT()
    With CreateObject("ADODB.Recordset")
        .Open ("Select F1,Sum(F2),Avg(F3),Avg(F4),Avg(F5) From [Sheet1$B6:F] Group By F1"), "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & ThisWorkbook.FullName & ";Extended Properties=""Excel 12.0 Xml;HDR=No"""
        Sheet1.Range("H12").CopyFromRecordset .DataSource
    End With
End Sub
 
Upvote 0
Thêm cách khác tham khảo
Mã:
Option Explicit
Sub ABC()
    Dim Dic As Object, sArr(), Res(), i&, Key, S, K&, j&
    Set Dic = CreateObject("Scripting.dictionary")
    With Sheets("Sheet1")
        sArr = .Range("B5:F" & .Range("B" & Rows.Count).End(3).Row).Value
        ReDim Res(1 To UBound(sArr), 1 To 5)
        For i = 2 To UBound(sArr)
            Dic(sArr(i, 1)) = Dic(sArr(i, 1)) & "," & i
        Next
        For Each Key In Dic.keys
            K = K + 1
            Res(K, 1) = Key
            S = Split(Dic(Key), ",")
            For i = 1 To UBound(S)
                For j = 2 To UBound(sArr, 2)
                    Res(K, j) = Res(K, j) + sArr(--S(i), j)
                Next
            Next
            For j = 3 To UBound(sArr, 2)
                Res(K, j) = Res(K, j) / UBound(S)
            Next
        Next
        .Range("H13:L1000").ClearContents
        .Range("H13").Resize(K, 5).Value = Res
    End With
End Sub
Một cách viết khác dựa trên code bạn:
Mã:
Option Explicit
Sub ABC1()
    Dim Dic As Object, sArr(), Res(), i&, sKey$, K&, j&, sItem
    Set Dic = CreateObject("Scripting.dictionary")
    With Sheets("Sheet1")
        sArr = .Range("B6:F" & .Range("B" & Rows.Count).End(3).Row).Value
        ReDim Res(1 To UBound(sArr), 1 To 5)
        For i = 1 To UBound(sArr)
            sKey = sArr(i, 1)
            If Not Dic.exists(sKey) Then
                K = K + 1
                Dic.Add sKey, Array(K, 1)
                Res(K, 1) = sKey
            Else
                sItem = Dic.Item(sKey)
                sItem(1) = sItem(1) + 1
                Dic.Item(sKey) = sItem
            End If
            sItem = Dic.Item(sKey)
            Res(sItem(0), 2) = Res(sItem(0), 2) + sArr(i, 2)
            For j = 3 To UBound(sArr, 2)
                Res(sItem(0), j) = (Res(sItem(0), j) * (sItem(1) - 1) + sArr(i, j)) / sItem(1)
            Next
        Next
        .Range("H13:L1000").ClearContents
        .Range("H13").Resize(K, 5).Value = Res
    End With
End Sub
 
Upvote 0
Web KT

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

Back
Top Bottom