Sắp xếp lấy TOP 4 theo nhiều điều kiện

Liên hệ QC

alex-luu

Thành viên thường trực
Tham gia
10/3/15
Bài viết
300
Được thích
52
Nhờ các anh chị giúp em hàm hoặc code sắp xếp lấy TOP 4 điểm cao nhất theo các điều kiện sau đây
Em có bảng dữ liệu như sau :

1632817364408.png

Em cần xếp hạng TOP 4 cho 2 cột AB và AC (kết quả đưa vào cột AD và AE) theo tiêu chí sau :

1632817889424.png

Lưu ý : xét tổng điểm tháng để lấy TOP tháng , Nhớ xem ô AH1 : user nhập tháng nào thì chỉ dò theo cột A để xét tháng đó.
- Tức là nếu giả sử tháng đó, điểm cao nhất ở cột AB mà <18 thì xem như tháng đó không có ai đạt.
- Điểm cao nhất ở cột AB mà >=18 thì xét tiếp tiêu chí phụ là cột M : tỉ lệ EHC phải >=60%, nếu không đạt thì cũng xem như bỏ.
Nếu thỏa hết 2 điều kiện trên thì sẽ xét tiếp tiêu chí phân loại (theo thứ tự ưu tiên :
* Nếu điểm tổng = nhau thì xét tỉ lệ EHC (cột M) ai cao hơn thì lấy TOP .
* Nếu tỉ lệ EHC cũng bằng nhau luôn thì xét tiếp SL Code cấp (cột K).
* Nếu vẫn = nhau thì xét tiếp FYC (cột O). Đến khi 3 cột phụ này mà vẫn = nhau thì đành phải cho đồng hạng.
 

File đính kèm

  • Book1.xlsx
    120.8 KB · Đọc: 20
Lần chỉnh sửa cuối:
Máy bạn có cài cài cái này NET Framework không.
Windows luôn luôn mặc định có sẵn .NET Framework.
Đúng chuẩn Windows bản quyền, hàng 'ngon' thì mặc định .NET Framework bật lên luôn.
Chỉ một số ít trường hợp bản Windows lởm khởm mới dính lỗi .NET Framework không chạy.
 
Ở cột AB nó trùng nhau thì lấy sao ta.Máy bạn có cài cài cái này NET Framework không.
Cứ xét tổng điểm tháng để lấy TOP tháng thôi anh, Nhớ xem ô AH1 : user nhập tháng nào thì chỉ dò theo cột A để xét tháng đó.
Tức là nếu giả sử tháng đó, điểm cao nhất ở cột AB mà <18 thì xem như tháng đó không có ai đạt.
Điểm cao nhất ở cột AB mà >=18 thì xét tiếp tiêu chí phụ là cột M : tỉ lệ EHC phải >=60%, nếu không đạt thì cũng xem như bỏ.
Nếu thỏa hết 2 điều kiện trên thì sẽ xét tiếp tiêu chí phân loại (theo thứ tự ưu tiên :
Nếu điểm tổng = nhau thì xét tỉ lệ EHC (cột M) ai cao hơn thì lấy TOP . Nếu tỉ lệ EHC cũng bằng nhau luôn thì xét tiếp SL Code cấp (cột K). Nếu vẫn = nhau thì xét tiếp FYC (cột O). Đến khi 3 cột phụ này mà vẫn = nhau thì đành phải cho đồng hạng.
 
Lần chỉnh sửa cuối:
Nhờ các anh chị giúp em hàm hoặc code sắp xếp lấy TOP 4 điểm cao nhất theo các điều kiện sau đây
Em có bảng dữ liệu như sau :

View attachment 266862

Em cần xếp hạng TOP 4 cho 2 cột AB và AC (kết quả đưa vào cột AD và AE) theo tiêu chí sau :

View attachment 266865

Lưu ý : xét tổng điểm tháng để lấy TOP tháng , Nhớ xem ô AH1 : user nhập tháng nào thì chỉ dò theo cột A để xét tháng đó.
- Tức là nếu giả sử tháng đó, điểm cao nhất ở cột AB mà <18 thì xem như tháng đó không có ai đạt.
- Điểm cao nhất ở cột AB mà >=18 thì xét tiếp tiêu chí phụ là cột M : tỉ lệ EHC phải >=60%, nếu không đạt thì cũng xem như bỏ.
Nếu thỏa hết 2 điều kiện trên thì sẽ xét tiếp tiêu chí phân loại (theo thứ tự ưu tiên :
* Nếu điểm tổng = nhau thì xét tỉ lệ EHC (cột M) ai cao hơn thì lấy TOP .
* Nếu tỉ lệ EHC cũng bằng nhau luôn thì xét tiếp SL Code cấp (cột K).
* Nếu vẫn = nhau thì xét tiếp FYC (cột O). Đến khi 3 cột phụ này mà vẫn = nhau thì đành phải cho đồng hạng.
Không xét loại trùng hạng
Mã:
AD2 =IFERROR(MATCH(IF(AND(A2=$AH$1,M2>=0.6),AB2,"No Ok"),AGGREGATE(14,6,$AB$2:$AB$426/($A$2:$A$426=$AH$1)/($AB$2:$AB$426>=18)/($M$2:$M$426>=0.6),{1,2,3,4}),0),"")
AE2 =IFERROR(MATCH(IF(AND(X2>=0.65,DATEDIF(S2,TODAY(),"M")>=3,H2<>H1),AC2,"No Ok"),AGGREGATE(14,6,$AC$2:$AC$426/($H$2:$H$426<>$H$1:$H$425)/($AC$2:$AC$426>=180)/($X$2:$X$426>=0.65),{1,1}),0),IFERROR(MATCH(IF(AND(X2>=0.6,DATEDIF(S2,TODAY(),"M")>=3,H2<>H1),AC2,"No Ok"),AGGREGATE(14,6,$AC$2:$AC$426/($H$2:$H$426<>$H$1:$H$425)/($AC$2:$AC$426>=180)/($X$2:$X$426>=0.6),{0,2,3,4}),0),""))
 
Nhìn Function của anh @HieuCD thấy bài toán khó ghê.
Nếu dùng Advanced filter để lọc ra top 4 rồi sort ở 1 bảng khác thì đơn giản đi nhiều.
 
Không xét loại trùng hạng
Mã:
AD2 =IFERROR(MATCH(IF(AND(A2=$AH$1,M2>=0.6),AB2,"No Ok"),AGGREGATE(14,6,$AB$2:$AB$426/($A$2:$A$426=$AH$1)/($AB$2:$AB$426>=18)/($M$2:$M$426>=0.6),{1,2,3,4}),0),"")
AE2 =IFERROR(MATCH(IF(AND(X2>=0.65,DATEDIF(S2,TODAY(),"M")>=3,H2<>H1),AC2,"No Ok"),AGGREGATE(14,6,$AC$2:$AC$426/($H$2:$H$426<>$H$1:$H$425)/($AC$2:$AC$426>=180)/($X$2:$X$426>=0.65),{1,1}),0),IFERROR(MATCH(IF(AND(X2>=0.6,DATEDIF(S2,TODAY(),"M")>=3,H2<>H1),AC2,"No Ok"),AGGREGATE(14,6,$AC$2:$AC$426/($H$2:$H$426<>$H$1:$H$425)/($AC$2:$AC$426>=180)/($X$2:$X$426>=0.6),{0,2,3,4}),0),""))
Cảm ơn bạn . Hàm chạy đúng kết quả.
Nhưng nếu được , bạn giúp mình ràng thêm trường hợp xét 2 tiêu chí phụ để hạn chế trường hợp đồng hạng nhé.
Nếu đồng hạng thì xét theo thứ tự : tỉ lệ EHC ((cột M), nếu vẫn trùng thì xét số lượng code cấp (cột K), vẫn trùng thì xét cột FYC (cột O). Nếu vẫn trùng thì lúc này mới đồng hạng.
Do danh sách của mình nó sẽ chạy 1 năm với số hàng khoảng 10.000 hàng nên khả năng đồng hạng sẽ có.
Cảm ơn bạn rất nhiều
 
Cảm ơn bạn . Hàm chạy đúng kết quả.
Nhưng nếu được , bạn giúp mình ràng thêm trường hợp xét 2 tiêu chí phụ để hạn chế trường hợp đồng hạng nhé.
Nếu đồng hạng thì xét theo thứ tự : tỉ lệ EHC ((cột M), nếu vẫn trùng thì xét số lượng code cấp (cột K), vẫn trùng thì xét cột FYC (cột O). Nếu vẫn trùng thì lúc này mới đồng hạng.
Do danh sách của mình nó sẽ chạy 1 năm với số hàng khoảng 10.000 hàng nên khả năng đồng hạng sẽ có.
Cảm ơn bạn rất nhiều
Với cách tính tổng điểm rắc rối nầy, khả năng trùng gần như bằng 0, dữ liệu nhiều phải dùng sub VBA
 
Cảm ơn bạn . Hàm chạy đúng kết quả.
Nhưng nếu được , bạn giúp mình ràng thêm trường hợp xét 2 tiêu chí phụ để hạn chế trường hợp đồng hạng nhé.
Nếu đồng hạng thì xét theo thứ tự : tỉ lệ EHC ((cột M), nếu vẫn trùng thì xét số lượng code cấp (cột K), vẫn trùng thì xét cột FYC (cột O). Nếu vẫn trùng thì lúc này mới đồng hạng.
Do danh sách của mình nó sẽ chạy 1 năm với số hàng khoảng 10.000 hàng nên khả năng đồng hạng sẽ có.
Cảm ơn bạn rất nhiều
Top 4 của năm, cách tính các cột K, M, O như thế nào?
 
Top 4 của tháng, nếu chuyển kết quả sang 1 Sheet khác, dùng Power Query để Filter các điều kiện của đề bài cho ra TopMonth.
 

File đính kèm

  • SapXepThuHang.xlsx
    138.5 KB · Đọc: 17
Top 4 của năm, cách tính các cột K, M, O như thế nào?
cũng y vậy luôn bạn, TOP 4 của năm thì không xét giá trị của ô AH1 mà tính toàn bộ cả năm (cột A). Xét giá trị lớn nhất từ trên xuống ở cột AC để lấy TOP4

Điều kiện để được xét TOP 4 của năm là tối thiểu phải thỏa 3 điều kiện :
* Cột ngày gia nhập : chỉ tính những người đã làm việc từ 3 tháng trở lên (cột S)
* Đối với vị trí TOP1 : Tổng điểm năm phải >=180 (cột AC) VÀ tỉ lệ EHC trung bình quy năm (lúc này là xét cột X chứ không phải cột M nhé, vì cột M là tỉ lệ EHC theo tháng thôi) >=65%.
* Đối với TOP 2 , 3 , 4 : Tổng điểm năm phải >=180 (cột AC) VÀ tỉ lệ EHC trung bình quy năm (Cột X) >=60%.

Nếu bằng nhau thì xét tiếp các tiêu chí phụ sau (theo thứ tự ưu tiên)
Tỉ lệ EHC trung bình quy năm (cột X) lớn hơn thì đạt top cao hơn
Nếu bằng nhau thì xét tiếp SL code cấp quy trung bình theo năm (lấy trung bình theo năm của cột K theo trainer code) nhiều hơn thì đạt TOP cao hơn
Nếu vẫn bằng nhau thì xét tiếp tổng FYC quy năm (cột O : nhưng phải SUM FYC cả năm của người đó lại, cái này em chưa SUM , có lẽ cần phải tạo 1 cột phụ để SUM FYC quy năm hay không ?
Nếu vẫn bằng nhau thì lúc này phải chấp nhận đồng hạng.
 
Lần chỉnh sửa cuối:
cũng y vậy luôn bạn, TOP 4 của năm thì không xét giá trị của ô AH1 mà tính toàn bộ cả năm (cột A). Xét giá trị lớn nhất từ trên xuống ở cột AC để lấy TOP4

Điều kiện để được xét TOP 4 của năm là tối thiểu phải thỏa 3 điều kiện :
* Cột ngày gia nhập : chỉ tính những người đã làm việc từ 3 tháng trở lên (cột S)
* Đối với vị trí TOP1 : Tổng điểm năm phải >=180 (cột AC) VÀ tỉ lệ EHC trung bình quy năm (lúc này là xét cột X chứ không phải cột M nhé, vì cột M là tỉ lệ EHC theo tháng thôi) >=65%.
* Đối với TOP 2 , 3 , 4 : Tổng điểm năm phải >=180 (cột AC) VÀ tỉ lệ EHC trung bình quy năm (Cột X) >=60%.

Nếu bằng nhau thì xét tiếp các tiêu chí phụ sau (theo thứ tự ưu tiên)
Tỉ lệ EHC trung bình quy năm (cột X) lớn hơn thì đạt top cao hơn
Nếu bằng nhau thì xét tiếp SL code cấp (cột K) nhiều hơn thì đạt TOP cao hơn
Nếu vẫn bằng nhau thì xét tiếp tổng FYC quy năm (cột O : nhưng phải SUM FYC cả năm của người đó lại, cái này em chưa SUM , có lẽ cần phải tạo 1 cột phụ để SUM FYC quy năm hay không ?
Nếu vẫn bằng nhau thì lúc này phải chấp nhận đồng hạng.
Cột X trong file = tổng/9 tháng mặc dù có người chỉ làm 8 tháng
Vậy các cột K, M, O tính tổng hay lấy tổng / số tháng thực tế
 
Cột X trong file = tổng/9 tháng mặc dù có người chỉ làm 8 tháng
Vậy các cột K, M, O tính tổng hay lấy tổng / số tháng thực tế
Ôi, vậy là cái này em đang làm sai rồi. Em không nghĩ đến tình huống có người làm 9 tháng, có người vô sau nên sẽ ít hơn. Lúc đầu em còn chia luôn cho 12, nhưng sau nghĩ không đúng nên em chia kiểu đang làm, ai dè như anh phát hiện, thế là vẫn sai.
Phải chia theo số tháng thực tế của từng người mới công bằng và chính xác anh ơi., các cột kia cũng vậy. Đã tính chỗ thưởng năm thì phải tính theo số tháng thực tế của từng người trong năm đó
Bài đã được tự động gộp:

Top 4 của tháng, nếu chuyển kết quả sang 1 Sheet khác, dùng Power Query để Filter các điều kiện của đề bài cho ra TopMonth.
Em không hiểu gì về power query nện không dám dùng cách này, vì lỡ trong quá trình sử dụng, có phát sinh bất cứ vấn đề nào thì không biết hỏi ai anh ạ. Chắc sau hôm nay sẽ dành ít thời gian lên google tìm hiểu thêm về power query, bữa giờ có hỏi mấy vấn đề, thấy có vài anh cũng bảo làm bằng power query. Em cảm ơn anh ạ
 
Lần chỉnh sửa cuối:
Cột X trong file = tổng/9 tháng mặc dù có người chỉ làm 8 tháng
Vậy các cột K, M, O tính tổng hay lấy tổng / số tháng thực tế
à, bạn HieuCD ơi , bạn nói vậy thì mình lại nghĩ đến 1 trường hợp nữa, không nên dò theo tên người vì tên người hoàn toàn có thể trùng nhau. bạn vui lòng unhide cột B ra dùm, mình dò theo cột B là trainer code thì sẽ không bao giờ bị trùng.
"Vậy các cột K, M, O tính tổng hay lấy tổng / số tháng thực tế" : tính tổng /số tháng thực tế của người đó nhé.
Cảm ơn bạn.
 
Em không hiểu gì về power query nện không dám dùng cách này, vì lỡ trong quá trình sử dụng, có phát sinh bất cứ vấn đề nào thì không biết hỏi ai anh ạ. Chắc sau hôm nay sẽ dành ít thời gian lên google tìm hiểu thêm về power query, bữa giờ có hỏi mấy vấn đề, thấy có vài anh cũng bảo làm bằng power query. Em cảm ơn anh ạ
Hỏi ở trên GPE này luôn bạn. Có 1 box chuyên về Power Query mà.
 
à, bạn HieuCD ơi , bạn nói vậy thì mình lại nghĩ đến 1 trường hợp nữa, không nên dò theo tên người vì tên người hoàn toàn có thể trùng nhau. bạn vui lòng unhide cột B ra dùm, mình dò theo cột B là trainer code thì sẽ không bao giờ bị trùng.
"Vậy các cột K, M, O tính tổng hay lấy tổng / số tháng thực tế" : tính tổng /số tháng thực tế của người đó nhé.
Cảm ơn bạn.
10.000 dòng dùng công thức không khả thi. Chạy sub XYZ
Tạo 1 module lưu "Function SortArray2D" sort các mảng dữ liệu
Mã:
Option Explicit
Function SortArray2D(ByVal sArr, ByVal aCol, Optional bHeader As Boolean = False) As Variant
  'Sort Mang 2 chieu "sArr" theo nhieu Cot
  'aCol: So hoac Mang so, so duong tu A => Z, so am tu Z => A
  'Ví du aCol:'          2:  Sort theo cot 2 tu A => Z
              '         -3:  Sort theo cot 3 tu Z => A
              'Array(2,-4): (VBA) Sort theo cot 2 tu A => Z va Sort theo cot 4 tu Z => A
              '{2,-4}:      (Cong thuc trong Sheet) Sort theo cot 2 tu A => Z va Sort theo cot 4 tu Z => A
  'bHead = True Du lieu co dong tieu de. Mac dinh bHead = False Du lieu khong co dong tieu de
  Dim aRow, res()
  Dim sRow&, fRow&, eRow&, fCol&, eCol&, b&, i&, r&, k&, j&
 
  If TypeName(sArr) = "Range" Then sArr = sArr.Value
  If IsArray(sArr) = False Then Exit Function
  fRow = LBound(sArr, 1):   eRow = UBound(sArr, 1)
  fCol = LBound(sArr, 2):   eCol = UBound(sArr, 2)
  If IsArray(aCol) = False Then aCol = Array(aCol) 'Mang thu tu cot Sort
  If bHeader Then b = 1
  sRow = eRow - fRow - b
  ReDim aRow(0 - b To sRow) 'Mang thu tu dong du lieu goc
  For i = fRow To eRow
    aRow(i - fRow - b) = i
  Next i
  Call ChiaDuLieu(aRow, sArr, 0, sRow, aCol(LBound(aCol))) 'Sort theo cot 1
  If UBound(aCol) > LBound(aCol) Then 'Sort theo cac cot ke tiep
    Call DeQui(sArr, aRow, aCol, LBound(aCol) + 1, 0, sRow)
  End If

  k = fRow - 1
  ReDim res(fRow To eRow, fCol To eCol) 'Mang ket qua
  For i = 0 - b To sRow
    k = k + 1
    r = aRow(i)
    For j = fCol To eCol
      res(k, j) = sArr(r, j)
    Next j
  Next i
  SortArray2D = res
End Function

Private Sub DeQui(sArr, aRow, aCol, ByVal n&, ByVal fRow&, ByVal eRow&)
  Dim tmp, tmp2, i&, fR&, jCol&
 
  jCol = Abs(aCol(n - 1)) 'Thu tu cot da Sort truoc
  fR = -1
  tmp = sArr(aRow(fRow), jCol)
  If IsError(tmp) Then tmp = "Error!@#"
  For i = fRow To eRow - 1
    If i > 0 Then tmp = tmp2
    tmp2 = sArr(aRow(i + 1), jCol)
    If IsError(tmp2) Then tmp2 = "Error!@#"
    If fR = -1 Then
      If tmp = tmp2 Then fR = i
    End If
    If fR > -1 Then
      If tmp <> tmp2 Then
        Call ChiaDuLieu(aRow, sArr, fR, i, aCol(n))
        If n < UBound(aCol) Then
          Call DeQui(sArr, aRow, aCol, n + 1, fR, i) 'Sort cot ke tiep
        End If
        fR = -1
      ElseIf i = eRow - 1 Then
        Call ChiaDuLieu(aRow, sArr, fR, eRow, aCol(n))
        If n < UBound(aCol) Then
          Call DeQui(sArr, aRow, aCol, n + 1, fR, eRow) 'Sort cot ke tiep
        End If
      End If
    End If
  Next i
End Sub

Private Sub ChiaDuLieu(aRow, sArr, ByVal fRow&, ByVal eRow&, ByVal jCol&)
  Dim oListStr As Object, oListNum As Object
  Dim aErr, aEmp, aNum, aStr, arr
  Dim td$, tdUp$, tmp, bASC As Boolean
  Dim i&, n&, k0&, k1&, k2&, k3&
 
  Set oListStr = CreateObject("System.Collections.ArrayList")
  Set oListNum = CreateObject("System.Collections.ArrayList")
  arr = Array(-1, -1, -1, -1) ' Loi, Rong, So, Chuoi
  td = ChrW(273):       tdUp = ChrW(272)
  bASC = jCol > 0:      jCol = Abs(jCol)
  For n = fRow To eRow 'Dem cac loai du lieu
    tmp = sArr(aRow(n), jCol)
    If IsError(tmp) Then 'du lieu error
      arr(0) = arr(0) + 1
    ElseIf IsEmpty(tmp) Then 'du lieu Rong
      arr(1) = arr(1) + 1
    ElseIf IsNumeric(tmp) = True Then 'du lieu So
      arr(2) = arr(2) + 1
    Else 'du lieu Chuoi
      arr(3) = arr(3) + 1
    End If
  Next n
  If arr(0) >= 0 Then ReDim aErr(0 To arr(0))
  If arr(1) >= 0 Then ReDim aEmp(0 To arr(1))
  If arr(2) >= 0 Then ReDim aNum(0 To arr(2))
  If arr(3) >= 0 Then ReDim aStr(0 To arr(3))
  For n = fRow To eRow 'Gan cac loai du lieu vao mang tuong ung
    i = aRow(n)
    tmp = sArr(i, jCol)
    If IsError(tmp) Then
      k0 = k0 + 1:  aErr(k0 - 1) = i
    ElseIf IsEmpty(tmp) Then
      k1 = k1 + 1:  aEmp(k1 - 1) = i
    ElseIf IsNumeric(tmp) = True Then
      k2 = k2 + 1:  aNum(k2 - 1) = i
      oListNum.Add tmp
    Else
      If InStr(1, tmp, td, vbBinaryCompare) > 0 Then tmp = Replace(tmp, td, "dzz")
      If InStr(1, tmp, tdUp, vbBinaryCompare) > 0 Then tmp = Replace(tmp, tdUp, "Dzz")
      k3 = k3 + 1:  aStr(k3 - 1) = i
      oListStr.Add tmp
    End If
  Next n
  If k2 > 0 Then aNum = SortRow(oListNum, aNum, bASC) 'Sort du lieu So
  If k3 > 0 Then aStr = SortRow(oListStr, aStr, bASC) 'Sort du lieu Chuoi
  If bASC Then
    arr = Array(aNum, aStr, aErr, aEmp) ' So, Chuoi, Loi, Rong
  Else
    arr = Array(aStr, aNum, aErr, aEmp) ' Chuoi, So, Loi, Rong
  End If
  k1 = fRow - 1
  For n = 0 To 3
    If IsArray(arr(n)) Then
      For i = 0 To UBound(arr(n))
        k1 = k1 + 1
        aRow(k1) = arr(n)(i)
      Next i
    End If
  Next n
  Set oListNum = Nothing:   Set oListStr = Nothing
End Sub

Private Function SortRow(tList, aSort, bASC) As Variant
  Dim arr(), i&, k&, r&, tmp, oList As Object
 
  On Error Resume Next
  ReDim arr(0 To UBound(aSort))
  Set oList = tList.Clone
  tList.Sort
  If bASC = False Then tList.Reverse
  For i = 0 To tList.Count - 1
    tmp = tList.Item(i)
    r = oList.IndexOf(tmp, 0)
    If tmp = tList.Item(i + 1) Then oList.Item(r) = Empty
      k = k + 1
      arr(k - 1) = aSort(r)
  Next i
  SortRow = arr
  Set oList = Nothing
End Function
Tạo thêm 1 module lưu code xử lý kết quả
Mã:
Option Explicit
Sub XYZ()
  Dim sArr(), aThang(), aNam(), aEHC(), arr(), res()
  Dim NamThang&, sRow&, i&, iR&, n&, k&, k2&, iD&
  Dim nv$, SLC#, EHC#, FYC#, nMax#
  Const top& = 4
 
  With Sheet1
    NamThang = .Range("AH1").Value
    sArr = .Range("A2:AC" & .Range("AC" & Rows.Count).End(xlUp).Row + 1).Value
  End With
  sRow = UBound(sArr) - 1
  ReDim aThang(1 To sRow, 1 To 5)
  ReDim aNam(1 To sRow, 1 To 5)
  ReDim aEHC(1 To sRow, 1 To 1)
'Loc du lieu theo dieu kien
  For i = 1 To sRow
    If sArr(i, 1) = NamThang Then
      If sArr(i, 13) >= 0.6 Then 'Cot M   0.6
        If sArr(i, 28) >= 18 Then 'Cot AB  18 ***
          k = k + 1
          aThang(k, 1) = sArr(i, 28) 'Cot AB
          aThang(k, 2) = sArr(i, 13) 'Cot M
          aThang(k, 3) = sArr(i, 11) 'Cot K
          aThang(k, 4) = sArr(i, 15) 'Cot O
          aThang(k, 5) = i
        End If
      End If
    End If
    If nv <> sArr(i, 2) Then 'ma NV
      nv = sArr(i, 2)
      iR = i 'Dong dau cua NV
      n = 0: SLC = 0: EHC = 0: FYC = 0
    End If
    n = n + 1
    SLC = SLC + sArr(i, 11) 'Cot K
    EHC = EHC + sArr(i, 13) 'Cot M
    FYC = FYC + sArr(i, 15) 'Cot O
    If nv <> sArr(i + 1, 2) Then
      aEHC(iR, 1) = EHC / n 'Cot X  (cot M)
      If DateAdd("m", 3, sArr(i, 19)) <= Date Then '3 thang
        If sArr(i, 29) >= 180 Then 'Cot AC    180 ***
          If aEHC(iR, 1) >= 0.6 Then 'Cot X   0.6, 0.65
            k2 = k2 + 1
            aNam(k2, 1) = sArr(i, 29) 'Cot AC
            aNam(k2, 2) = aEHC(iR, 1) 'Cot X  (cot M)
            aNam(k2, 3) = SLC / n 'Cot K
            aNam(k2, 4) = FYC / n 'Cot O
            aNam(k2, 5) = iR
          End If
        End If
      End If
    End If
  Next i
'Sort du lieu va Lay Ket Qua
  ReDim res(1 To sRow, 1 To 2)
  Call LoaiDongRong(aThang, k, 5)
  Call LoaiDongRong(aNam, k2, 5)
  aThang = SortArray2D(aThang, Array(-1, -2, -3, -4))
  If k > top Then k = top 'Top 4
  For i = 1 To k
    res(aThang(i, 5), 1) = i 'Top Thang
  Next i
  aNam = SortArray2D(aNam, Array(-1, -2, -3, -4))
  For i = 1 To k2
    If aNam(i, 2) >= 0.65 Then
      iD = 1
      res(aNam(i, 5), 2) = iD 'Top Nam
      aNam(i, 2) = 0
      Exit For
    End If
  Next i
  For i = 1 To k2
    If aNam(i, 2) >= 0.6 Then
      iD = iD + 1
      res(aNam(i, 5), 2) = iD 'Top Nam
      If iD = top Then Exit For
    End If
  Next i
  Sheet1.Range("AD2").Resize(sRow, 2) = res
  'Sheet1.Range("X2").Resize(sRow) = aEHC 'Tinh lai Ti le EHC trung binh
End Sub

Private Sub LoaiDongRong(ByRef sArr(), ByVal sRow&, ByVal sCol&)
  Dim arr(), i&, j&
  arr = sArr
  ReDim sArr(1 To sRow, 1 To 5)
  For i = 1 To sRow
    For j = 1 To sCol
      sArr(i, j) = arr(i, j)
    Next j
  Next i
End Sub
 

File đính kèm

  • Book1 (9).xlsm
    154.7 KB · Đọc: 25
10.000 dòng dùng công thức không khả thi. Chạy sub XYZ
Tạo 1 module lưu "Function SortArray2D" sort các mảng dữ liệu
Mã:
Option Explicit
Function SortArray2D(ByVal sArr, ByVal aCol, Optional bHeader As Boolean = False) As Variant
  'Sort Mang 2 chieu "sArr" theo nhieu Cot
  'aCol: So hoac Mang so, so duong tu A => Z, so am tu Z => A
  'Ví du aCol:'          2:  Sort theo cot 2 tu A => Z
              '         -3:  Sort theo cot 3 tu Z => A
              'Array(2,-4): (VBA) Sort theo cot 2 tu A => Z va Sort theo cot 4 tu Z => A
              '{2,-4}:      (Cong thuc trong Sheet) Sort theo cot 2 tu A => Z va Sort theo cot 4 tu Z => A
  'bHead = True Du lieu co dong tieu de. Mac dinh bHead = False Du lieu khong co dong tieu de
  Dim aRow, res()
  Dim sRow&, fRow&, eRow&, fCol&, eCol&, b&, i&, r&, k&, j&
 
  If TypeName(sArr) = "Range" Then sArr = sArr.Value
  If IsArray(sArr) = False Then Exit Function
  fRow = LBound(sArr, 1):   eRow = UBound(sArr, 1)
  fCol = LBound(sArr, 2):   eCol = UBound(sArr, 2)
  If IsArray(aCol) = False Then aCol = Array(aCol) 'Mang thu tu cot Sort
  If bHeader Then b = 1
  sRow = eRow - fRow - b
  ReDim aRow(0 - b To sRow) 'Mang thu tu dong du lieu goc
  For i = fRow To eRow
    aRow(i - fRow - b) = i
  Next i
  Call ChiaDuLieu(aRow, sArr, 0, sRow, aCol(LBound(aCol))) 'Sort theo cot 1
  If UBound(aCol) > LBound(aCol) Then 'Sort theo cac cot ke tiep
    Call DeQui(sArr, aRow, aCol, LBound(aCol) + 1, 0, sRow)
  End If

  k = fRow - 1
  ReDim res(fRow To eRow, fCol To eCol) 'Mang ket qua
  For i = 0 - b To sRow
    k = k + 1
    r = aRow(i)
    For j = fCol To eCol
      res(k, j) = sArr(r, j)
    Next j
  Next i
  SortArray2D = res
End Function

Private Sub DeQui(sArr, aRow, aCol, ByVal n&, ByVal fRow&, ByVal eRow&)
  Dim tmp, tmp2, i&, fR&, jCol&
 
  jCol = Abs(aCol(n - 1)) 'Thu tu cot da Sort truoc
  fR = -1
  tmp = sArr(aRow(fRow), jCol)
  If IsError(tmp) Then tmp = "Error!@#"
  For i = fRow To eRow - 1
    If i > 0 Then tmp = tmp2
    tmp2 = sArr(aRow(i + 1), jCol)
    If IsError(tmp2) Then tmp2 = "Error!@#"
    If fR = -1 Then
      If tmp = tmp2 Then fR = i
    End If
    If fR > -1 Then
      If tmp <> tmp2 Then
        Call ChiaDuLieu(aRow, sArr, fR, i, aCol(n))
        If n < UBound(aCol) Then
          Call DeQui(sArr, aRow, aCol, n + 1, fR, i) 'Sort cot ke tiep
        End If
        fR = -1
      ElseIf i = eRow - 1 Then
        Call ChiaDuLieu(aRow, sArr, fR, eRow, aCol(n))
        If n < UBound(aCol) Then
          Call DeQui(sArr, aRow, aCol, n + 1, fR, eRow) 'Sort cot ke tiep
        End If
      End If
    End If
  Next i
End Sub

Private Sub ChiaDuLieu(aRow, sArr, ByVal fRow&, ByVal eRow&, ByVal jCol&)
  Dim oListStr As Object, oListNum As Object
  Dim aErr, aEmp, aNum, aStr, arr
  Dim td$, tdUp$, tmp, bASC As Boolean
  Dim i&, n&, k0&, k1&, k2&, k3&
 
  Set oListStr = CreateObject("System.Collections.ArrayList")
  Set oListNum = CreateObject("System.Collections.ArrayList")
  arr = Array(-1, -1, -1, -1) ' Loi, Rong, So, Chuoi
  td = ChrW(273):       tdUp = ChrW(272)
  bASC = jCol > 0:      jCol = Abs(jCol)
  For n = fRow To eRow 'Dem cac loai du lieu
    tmp = sArr(aRow(n), jCol)
    If IsError(tmp) Then 'du lieu error
      arr(0) = arr(0) + 1
    ElseIf IsEmpty(tmp) Then 'du lieu Rong
      arr(1) = arr(1) + 1
    ElseIf IsNumeric(tmp) = True Then 'du lieu So
      arr(2) = arr(2) + 1
    Else 'du lieu Chuoi
      arr(3) = arr(3) + 1
    End If
  Next n
  If arr(0) >= 0 Then ReDim aErr(0 To arr(0))
  If arr(1) >= 0 Then ReDim aEmp(0 To arr(1))
  If arr(2) >= 0 Then ReDim aNum(0 To arr(2))
  If arr(3) >= 0 Then ReDim aStr(0 To arr(3))
  For n = fRow To eRow 'Gan cac loai du lieu vao mang tuong ung
    i = aRow(n)
    tmp = sArr(i, jCol)
    If IsError(tmp) Then
      k0 = k0 + 1:  aErr(k0 - 1) = i
    ElseIf IsEmpty(tmp) Then
      k1 = k1 + 1:  aEmp(k1 - 1) = i
    ElseIf IsNumeric(tmp) = True Then
      k2 = k2 + 1:  aNum(k2 - 1) = i
      oListNum.Add tmp
    Else
      If InStr(1, tmp, td, vbBinaryCompare) > 0 Then tmp = Replace(tmp, td, "dzz")
      If InStr(1, tmp, tdUp, vbBinaryCompare) > 0 Then tmp = Replace(tmp, tdUp, "Dzz")
      k3 = k3 + 1:  aStr(k3 - 1) = i
      oListStr.Add tmp
    End If
  Next n
  If k2 > 0 Then aNum = SortRow(oListNum, aNum, bASC) 'Sort du lieu So
  If k3 > 0 Then aStr = SortRow(oListStr, aStr, bASC) 'Sort du lieu Chuoi
  If bASC Then
    arr = Array(aNum, aStr, aErr, aEmp) ' So, Chuoi, Loi, Rong
  Else
    arr = Array(aStr, aNum, aErr, aEmp) ' Chuoi, So, Loi, Rong
  End If
  k1 = fRow - 1
  For n = 0 To 3
    If IsArray(arr(n)) Then
      For i = 0 To UBound(arr(n))
        k1 = k1 + 1
        aRow(k1) = arr(n)(i)
      Next i
    End If
  Next n
  Set oListNum = Nothing:   Set oListStr = Nothing
End Sub

Private Function SortRow(tList, aSort, bASC) As Variant
  Dim arr(), i&, k&, r&, tmp, oList As Object
 
  On Error Resume Next
  ReDim arr(0 To UBound(aSort))
  Set oList = tList.Clone
  tList.Sort
  If bASC = False Then tList.Reverse
  For i = 0 To tList.Count - 1
    tmp = tList.Item(i)
    r = oList.IndexOf(tmp, 0)
    If tmp = tList.Item(i + 1) Then oList.Item(r) = Empty
      k = k + 1
      arr(k - 1) = aSort(r)
  Next i
  SortRow = arr
  Set oList = Nothing
End Function
Tạo thêm 1 module lưu code xử lý kết quả
Mã:
Option Explicit
Sub XYZ()
  Dim sArr(), aThang(), aNam(), aEHC(), arr(), res()
  Dim NamThang&, sRow&, i&, iR&, n&, k&, k2&, iD&
  Dim nv$, SLC#, EHC#, FYC#, nMax#
  Const top& = 4
 
  With Sheet1
    NamThang = .Range("AH1").Value
    sArr = .Range("A2:AC" & .Range("AC" & Rows.Count).End(xlUp).Row + 1).Value
  End With
  sRow = UBound(sArr) - 1
  ReDim aThang(1 To sRow, 1 To 5)
  ReDim aNam(1 To sRow, 1 To 5)
  ReDim aEHC(1 To sRow, 1 To 1)
'Loc du lieu theo dieu kien
  For i = 1 To sRow
    If sArr(i, 1) = NamThang Then
      If sArr(i, 13) >= 0.6 Then 'Cot M   0.6
        If sArr(i, 28) >= 18 Then 'Cot AB  18 ***
          k = k + 1
          aThang(k, 1) = sArr(i, 28) 'Cot AB
          aThang(k, 2) = sArr(i, 13) 'Cot M
          aThang(k, 3) = sArr(i, 11) 'Cot K
          aThang(k, 4) = sArr(i, 15) 'Cot O
          aThang(k, 5) = i
        End If
      End If
    End If
    If nv <> sArr(i, 2) Then 'ma NV
      nv = sArr(i, 2)
      iR = i 'Dong dau cua NV
      n = 0: SLC = 0: EHC = 0: FYC = 0
    End If
    n = n + 1
    SLC = SLC + sArr(i, 11) 'Cot K
    EHC = EHC + sArr(i, 13) 'Cot M
    FYC = FYC + sArr(i, 15) 'Cot O
    If nv <> sArr(i + 1, 2) Then
      aEHC(iR, 1) = EHC / n 'Cot X  (cot M)
      If DateAdd("m", 3, sArr(i, 19)) <= Date Then '3 thang
        If sArr(i, 29) >= 180 Then 'Cot AC    180 ***
          If aEHC(iR, 1) >= 0.6 Then 'Cot X   0.6, 0.65
            k2 = k2 + 1
            aNam(k2, 1) = sArr(i, 29) 'Cot AC
            aNam(k2, 2) = aEHC(iR, 1) 'Cot X  (cot M)
            aNam(k2, 3) = SLC / n 'Cot K
            aNam(k2, 4) = FYC / n 'Cot O
            aNam(k2, 5) = iR
          End If
        End If
      End If
    End If
  Next i
'Sort du lieu va Lay Ket Qua
  ReDim res(1 To sRow, 1 To 2)
  Call LoaiDongRong(aThang, k, 5)
  Call LoaiDongRong(aNam, k2, 5)
  aThang = SortArray2D(aThang, Array(-1, -2, -3, -4))
  If k > top Then k = top 'Top 4
  For i = 1 To k
    res(aThang(i, 5), 1) = i 'Top Thang
  Next i
  aNam = SortArray2D(aNam, Array(-1, -2, -3, -4))
  For i = 1 To k2
    If aNam(i, 2) >= 0.65 Then
      iD = 1
      res(aNam(i, 5), 2) = iD 'Top Nam
      aNam(i, 2) = 0
      Exit For
    End If
  Next i
  For i = 1 To k2
    If aNam(i, 2) >= 0.6 Then
      iD = iD + 1
      res(aNam(i, 5), 2) = iD 'Top Nam
      If iD = top Then Exit For
    End If
  Next i
  Sheet1.Range("AD2").Resize(sRow, 2) = res
  'Sheet1.Range("X2").Resize(sRow) = aEHC 'Tinh lai Ti le EHC trung binh
End Sub

Private Sub LoaiDongRong(ByRef sArr(), ByVal sRow&, ByVal sCol&)
  Dim arr(), i&, j&
  arr = sArr
  ReDim sArr(1 To sRow, 1 To 5)
  For i = 1 To sRow
    For j = 1 To sCol
      sArr(i, j) = arr(i, j)
    Next j
  Next i
End Sub
Tuyệt vời ông mặt trời. cảm ơn bạn HieuCD rất là nhiều
 
10.000 dòng dùng công thức không khả thi. Chạy sub XYZ
Tạo 1 module lưu "Function SortArray2D" sort các mảng dữ liệu
Mã:
Option Explicit
Function SortArray2D(ByVal sArr, ByVal aCol, Optional bHeader As Boolean = False) As Variant
  'Sort Mang 2 chieu "sArr" theo nhieu Cot
  'aCol: So hoac Mang so, so duong tu A => Z, so am tu Z => A
  'Ví du aCol:'          2:  Sort theo cot 2 tu A => Z
              '         -3:  Sort theo cot 3 tu Z => A
              'Array(2,-4): (VBA) Sort theo cot 2 tu A => Z va Sort theo cot 4 tu Z => A
              '{2,-4}:      (Cong thuc trong Sheet) Sort theo cot 2 tu A => Z va Sort theo cot 4 tu Z => A
  'bHead = True Du lieu co dong tieu de. Mac dinh bHead = False Du lieu khong co dong tieu de
  Dim aRow, res()
  Dim sRow&, fRow&, eRow&, fCol&, eCol&, b&, i&, r&, k&, j&
 
  If TypeName(sArr) = "Range" Then sArr = sArr.Value
  If IsArray(sArr) = False Then Exit Function
  fRow = LBound(sArr, 1):   eRow = UBound(sArr, 1)
  fCol = LBound(sArr, 2):   eCol = UBound(sArr, 2)
  If IsArray(aCol) = False Then aCol = Array(aCol) 'Mang thu tu cot Sort
  If bHeader Then b = 1
  sRow = eRow - fRow - b
  ReDim aRow(0 - b To sRow) 'Mang thu tu dong du lieu goc
  For i = fRow To eRow
    aRow(i - fRow - b) = i
  Next i
  Call ChiaDuLieu(aRow, sArr, 0, sRow, aCol(LBound(aCol))) 'Sort theo cot 1
  If UBound(aCol) > LBound(aCol) Then 'Sort theo cac cot ke tiep
    Call DeQui(sArr, aRow, aCol, LBound(aCol) + 1, 0, sRow)
  End If

  k = fRow - 1
  ReDim res(fRow To eRow, fCol To eCol) 'Mang ket qua
  For i = 0 - b To sRow
    k = k + 1
    r = aRow(i)
    For j = fCol To eCol
      res(k, j) = sArr(r, j)
    Next j
  Next i
  SortArray2D = res
End Function

Private Sub DeQui(sArr, aRow, aCol, ByVal n&, ByVal fRow&, ByVal eRow&)
  Dim tmp, tmp2, i&, fR&, jCol&
 
  jCol = Abs(aCol(n - 1)) 'Thu tu cot da Sort truoc
  fR = -1
  tmp = sArr(aRow(fRow), jCol)
  If IsError(tmp) Then tmp = "Error!@#"
  For i = fRow To eRow - 1
    If i > 0 Then tmp = tmp2
    tmp2 = sArr(aRow(i + 1), jCol)
    If IsError(tmp2) Then tmp2 = "Error!@#"
    If fR = -1 Then
      If tmp = tmp2 Then fR = i
    End If
    If fR > -1 Then
      If tmp <> tmp2 Then
        Call ChiaDuLieu(aRow, sArr, fR, i, aCol(n))
        If n < UBound(aCol) Then
          Call DeQui(sArr, aRow, aCol, n + 1, fR, i) 'Sort cot ke tiep
        End If
        fR = -1
      ElseIf i = eRow - 1 Then
        Call ChiaDuLieu(aRow, sArr, fR, eRow, aCol(n))
        If n < UBound(aCol) Then
          Call DeQui(sArr, aRow, aCol, n + 1, fR, eRow) 'Sort cot ke tiep
        End If
      End If
    End If
  Next i
End Sub

Private Sub ChiaDuLieu(aRow, sArr, ByVal fRow&, ByVal eRow&, ByVal jCol&)
  Dim oListStr As Object, oListNum As Object
  Dim aErr, aEmp, aNum, aStr, arr
  Dim td$, tdUp$, tmp, bASC As Boolean
  Dim i&, n&, k0&, k1&, k2&, k3&
 
  Set oListStr = CreateObject("System.Collections.ArrayList")
  Set oListNum = CreateObject("System.Collections.ArrayList")
  arr = Array(-1, -1, -1, -1) ' Loi, Rong, So, Chuoi
  td = ChrW(273):       tdUp = ChrW(272)
  bASC = jCol > 0:      jCol = Abs(jCol)
  For n = fRow To eRow 'Dem cac loai du lieu
    tmp = sArr(aRow(n), jCol)
    If IsError(tmp) Then 'du lieu error
      arr(0) = arr(0) + 1
    ElseIf IsEmpty(tmp) Then 'du lieu Rong
      arr(1) = arr(1) + 1
    ElseIf IsNumeric(tmp) = True Then 'du lieu So
      arr(2) = arr(2) + 1
    Else 'du lieu Chuoi
      arr(3) = arr(3) + 1
    End If
  Next n
  If arr(0) >= 0 Then ReDim aErr(0 To arr(0))
  If arr(1) >= 0 Then ReDim aEmp(0 To arr(1))
  If arr(2) >= 0 Then ReDim aNum(0 To arr(2))
  If arr(3) >= 0 Then ReDim aStr(0 To arr(3))
  For n = fRow To eRow 'Gan cac loai du lieu vao mang tuong ung
    i = aRow(n)
    tmp = sArr(i, jCol)
    If IsError(tmp) Then
      k0 = k0 + 1:  aErr(k0 - 1) = i
    ElseIf IsEmpty(tmp) Then
      k1 = k1 + 1:  aEmp(k1 - 1) = i
    ElseIf IsNumeric(tmp) = True Then
      k2 = k2 + 1:  aNum(k2 - 1) = i
      oListNum.Add tmp
    Else
      If InStr(1, tmp, td, vbBinaryCompare) > 0 Then tmp = Replace(tmp, td, "dzz")
      If InStr(1, tmp, tdUp, vbBinaryCompare) > 0 Then tmp = Replace(tmp, tdUp, "Dzz")
      k3 = k3 + 1:  aStr(k3 - 1) = i
      oListStr.Add tmp
    End If
  Next n
  If k2 > 0 Then aNum = SortRow(oListNum, aNum, bASC) 'Sort du lieu So
  If k3 > 0 Then aStr = SortRow(oListStr, aStr, bASC) 'Sort du lieu Chuoi
  If bASC Then
    arr = Array(aNum, aStr, aErr, aEmp) ' So, Chuoi, Loi, Rong
  Else
    arr = Array(aStr, aNum, aErr, aEmp) ' Chuoi, So, Loi, Rong
  End If
  k1 = fRow - 1
  For n = 0 To 3
    If IsArray(arr(n)) Then
      For i = 0 To UBound(arr(n))
        k1 = k1 + 1
        aRow(k1) = arr(n)(i)
      Next i
    End If
  Next n
  Set oListNum = Nothing:   Set oListStr = Nothing
End Sub

Private Function SortRow(tList, aSort, bASC) As Variant
  Dim arr(), i&, k&, r&, tmp, oList As Object
 
  On Error Resume Next
  ReDim arr(0 To UBound(aSort))
  Set oList = tList.Clone
  tList.Sort
  If bASC = False Then tList.Reverse
  For i = 0 To tList.Count - 1
    tmp = tList.Item(i)
    r = oList.IndexOf(tmp, 0)
    If tmp = tList.Item(i + 1) Then oList.Item(r) = Empty
      k = k + 1
      arr(k - 1) = aSort(r)
  Next i
  SortRow = arr
  Set oList = Nothing
End Function
Tạo thêm 1 module lưu code xử lý kết quả
Mã:
Option Explicit
Sub XYZ()
  Dim sArr(), aThang(), aNam(), aEHC(), arr(), res()
  Dim NamThang&, sRow&, i&, iR&, n&, k&, k2&, iD&
  Dim nv$, SLC#, EHC#, FYC#, nMax#
  Const top& = 4
 
  With Sheet1
    NamThang = .Range("AH1").Value
    sArr = .Range("A2:AC" & .Range("AC" & Rows.Count).End(xlUp).Row + 1).Value
  End With
  sRow = UBound(sArr) - 1
  ReDim aThang(1 To sRow, 1 To 5)
  ReDim aNam(1 To sRow, 1 To 5)
  ReDim aEHC(1 To sRow, 1 To 1)
'Loc du lieu theo dieu kien
  For i = 1 To sRow
    If sArr(i, 1) = NamThang Then
      If sArr(i, 13) >= 0.6 Then 'Cot M   0.6
        If sArr(i, 28) >= 18 Then 'Cot AB  18 ***
          k = k + 1
          aThang(k, 1) = sArr(i, 28) 'Cot AB
          aThang(k, 2) = sArr(i, 13) 'Cot M
          aThang(k, 3) = sArr(i, 11) 'Cot K
          aThang(k, 4) = sArr(i, 15) 'Cot O
          aThang(k, 5) = i
        End If
      End If
    End If
    If nv <> sArr(i, 2) Then 'ma NV
      nv = sArr(i, 2)
      iR = i 'Dong dau cua NV
      n = 0: SLC = 0: EHC = 0: FYC = 0
    End If
    n = n + 1
    SLC = SLC + sArr(i, 11) 'Cot K
    EHC = EHC + sArr(i, 13) 'Cot M
    FYC = FYC + sArr(i, 15) 'Cot O
    If nv <> sArr(i + 1, 2) Then
      aEHC(iR, 1) = EHC / n 'Cot X  (cot M)
      If DateAdd("m", 3, sArr(i, 19)) <= Date Then '3 thang
        If sArr(i, 29) >= 180 Then 'Cot AC    180 ***
          If aEHC(iR, 1) >= 0.6 Then 'Cot X   0.6, 0.65
            k2 = k2 + 1
            aNam(k2, 1) = sArr(i, 29) 'Cot AC
            aNam(k2, 2) = aEHC(iR, 1) 'Cot X  (cot M)
            aNam(k2, 3) = SLC / n 'Cot K
            aNam(k2, 4) = FYC / n 'Cot O
            aNam(k2, 5) = iR
          End If
        End If
      End If
    End If
  Next i
'Sort du lieu va Lay Ket Qua
  ReDim res(1 To sRow, 1 To 2)
  Call LoaiDongRong(aThang, k, 5)
  Call LoaiDongRong(aNam, k2, 5)
  aThang = SortArray2D(aThang, Array(-1, -2, -3, -4))
  If k > top Then k = top 'Top 4
  For i = 1 To k
    res(aThang(i, 5), 1) = i 'Top Thang
  Next i
  aNam = SortArray2D(aNam, Array(-1, -2, -3, -4))
  For i = 1 To k2
    If aNam(i, 2) >= 0.65 Then
      iD = 1
      res(aNam(i, 5), 2) = iD 'Top Nam
      aNam(i, 2) = 0
      Exit For
    End If
  Next i
  For i = 1 To k2
    If aNam(i, 2) >= 0.6 Then
      iD = iD + 1
      res(aNam(i, 5), 2) = iD 'Top Nam
      If iD = top Then Exit For
    End If
  Next i
  Sheet1.Range("AD2").Resize(sRow, 2) = res
  'Sheet1.Range("X2").Resize(sRow) = aEHC 'Tinh lai Ti le EHC trung binh
End Sub

Private Sub LoaiDongRong(ByRef sArr(), ByVal sRow&, ByVal sCol&)
  Dim arr(), i&, j&
  arr = sArr
  ReDim sArr(1 To sRow, 1 To 5)
  For i = 1 To sRow
    For j = 1 To sCol
      sArr(i, j) = arr(i, j)
    Next j
  Next i
End Sub
Đúng là tuyệt vời, quá kỳ công cho 1 bài toán phức tạp.
Nếu lúc nào chủ topic muốn đơn giản hơn và tách các dữ liệu đáp ứng đúng tiêu chí hãy thử Power Query.
Tôi gửi File có cả code của anh @HieuCD và 2 bảng kết quả TopMonth, TopYear bằng PQ.
 

File đính kèm

  • SapXepThuHang.xlsm
    168.7 KB · Đọc: 26
Đúng là tuyệt vời, quá kỳ công cho 1 bài toán phức tạp.
Nếu lúc nào chủ topic muốn đơn giản hơn và tách các dữ liệu đáp ứng đúng tiêu chí hãy thử Power Query.
Tôi gửi File có cả code của anh @HieuCD và 2 bảng kết quả TopMonth, TopYear bằng PQ.
Dữ liệu nhiều cần tăng tốc độ xử lý nên code qua nhiều bước loại dần dữ liệu, sort trước xử lý sau code sẽ gọn hơn
 
Dữ liệu nhiều cần tăng tốc độ xử lý nên code qua nhiều bước loại dần dữ liệu, sort trước xử lý sau code sẽ gọn hơn
Vâng anh ạ, kể cả là 1 triệu records đi vẫn chơi PQ được, có chậm tí thì có thời gian nhâm nhi cốc Cafe.
 
Web KT
Back
Top Bottom