Sắp xếp lấy TOP 4 theo nhiều điều kiện (1 người xem)

Liên hệ QC

Người dùng đang xem chủ đề này

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

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

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

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

Đú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.
 
Em có một file có tô màu liên tiếp theo hàng ngang. mong muốn của e là viết code lấy 01 con số nằm ở ô cuối cùng của hàng đã được tô màu và tách sang cột riêng biệt. Em đã ghi nội dung cần trong file. Kính mong các Anh giúp đỡ.
 

File đính kèm

Em có một file có tô màu liên tiếp theo hàng ngang. mong muốn của e là viết code lấy 01 con số nằm ở ô cuối cùng của hàng đã được tô màu và tách sang cột riêng biệt. Em đã ghi nội dung cần trong file. Kính mong các Anh giúp đỡ.
Thử với code củ chuối này xem sao
Mã:
Option Explicit

Sub Mau()
Dim i&, j&, t&, Lr, Col&
Dim Rng As Range, Sh As Worksheet
Dim KQ()

Set Sh = Sheet1
Set Rng = Sh.Range("A2").CurrentRegion
Lr = Rng.Rows.Count: Col = Rng.Columns.Count
ReDim KQ(1 To Lr, 1 To Col)
For i = 1 To Lr
t = 0: k = 0
    For j = 1 To Col
        If Rng(i, j) <> Empty Then
            k = k + 1: If Rng(i, j).Interior.Color = vbYellow Then t = t + 1
        Else: Exit For
        End If
    Next j
        If t = 0 Then KQ(i, Col) = Rng(i, k) Else KQ(i, Col - t) = Rng(i, k)
Next i
Sh.[H2].Resize(i - 1, Col) = KQ
End Sub
 
Thử với code củ chuối này xem sao
Mã:
Option Explicit

Sub Mau()
Dim i&, j&, t&, Lr, Col&
Dim Rng As Range, Sh As Worksheet
Dim KQ()

Set Sh = Sheet1
Set Rng = Sh.Range("A2").CurrentRegion
Lr = Rng.Rows.Count: Col = Rng.Columns.Count
ReDim KQ(1 To Lr, 1 To Col)
For i = 1 To Lr
t = 0: k = 0
    For j = 1 To Col
        If Rng(i, j) <> Empty Then
            k = k + 1: If Rng(i, j).Interior.Color = vbYellow Then t = t + 1
        Else: Exit For
        End If
    Next j
        If t = 0 Then KQ(i, Col) = Rng(i, k) Else KQ(i, Col - t) = Rng(i, k)
Next i
Sh.[H2].Resize(i - 1, Col) = KQ
End Sub
Cám ơn Các anh! em đã thử chạy code tuy nhiên code báo lỗi ak. Mong các Anh/Chị bớt chút thời gian giúp sửa lại giùm em. nội dung mong muốn e ghi ở trong file ak. Một lần nữa xin chân thành cám ơn các Anh/Chị và xin chúc Anh/ Chị có ngày nghỉ cuối tuần vui vẻ hạnh phúc bên gia đình!
Trân trọng/
 

File đính kèm

Cám ơn Các anh! em đã thử chạy code tuy nhiên code báo lỗi ak. Mong các Anh/Chị bớt chút thời gian giúp sửa lại giùm em. nội dung mong muốn e ghi ở trong file ak. Một lần nữa xin chân thành cám ơn các Anh/Chị và xin chúc Anh/ Chị có ngày nghỉ cuối tuần vui vẻ hạnh phúc bên gia đình!
Trân trọng/
Bị lỗi ở k=0 đúng không? Do thiếu khai báo biến k
Bạn thêm k&, vào Dòng Dim.... như vầy Dim i&, j&, t&, k&, Lr, Col&
Và chạy thử.
Bạn có thể thêm nhiều dòng, cột nữa cho Dữ liệu (và nhớ là có khoảng trống là 1 cột, 1 dòng với vùng dữ liệu khác) , sau đó nhập vào Ô L1 địa chỉ ô muốn kết quả trả về. và nhấn nút==> xem và kiểm tra kết quả
Xem file đính kèm
 

File đính kèm

Bị lỗi ở k=0 đúng không? Do thiếu khai báo biến k
Bạn thêm k&, vào Dòng Dim.... như vầy Dim i&, j&, t&, k&, Lr, Col&
Và chạy thử.
Bạn có thể thêm nhiều dòng, cột nữa cho Dữ liệu (và nhớ là có khoảng trống là 1 cột, 1 dòng với vùng dữ liệu khác) , sau đó nhập vào Ô L1 địa chỉ ô muốn kết quả trả về. và nhấn nút==> xem và kiểm tra kết quả
Xem file đính kèm
thực sự không biết nói gì hơn ngoài lời cảm ơn chân thành tới Anh. Một lần nữa cảm ơn Anh
 
thực sự không biết nói gì hơn ngoài lời cảm ơn chân thành tới Anh. Một lần nữa cảm ơn Anh
Em đã sửa code và chạy, tuy nhiên có thêm vấn đề là tại ô A8 không có bôi màu code vẫn sắp xếp và không đếm được số lần mà ô có màu có dữ liệu. Em muốn Anh giúp em code thêm với nội dung e đã ghi trong file gửi đó ak!
Trân trọng/
 

File đính kèm

Em đã sửa code và chạy, tuy nhiên có thêm vấn đề là tại ô A8 không có bôi màu code vẫn sắp xếp và không đếm được số lần mà ô có màu có dữ liệu. Em muốn Anh giúp em code thêm với nội dung e đã ghi trong file gửi đó ak!
Trân trọng/
Sao mình thấy số 32 nằm ở chô khoanh đỏ này có đúng không nhỉ?
Có khi nào có trường hợp ở giữa không bôi màu không nhỉ
1646490390999.png
 
Em đã sửa code và chạy, tuy nhiên có thêm vấn đề là tại ô A8 không có bôi màu code vẫn sắp xếp và không đếm được số lần mà ô có màu có dữ liệu. Em muốn Anh giúp em code thêm với nội dung e đã ghi trong file gửi đó ak!
Trân trọng/
Tôi không được tinh anh như người khác. Bạn trình bày rõ hơn được không?
Nghĩa là dòng 8 dữ liệu có 5 ô và không có ô nào được tô màu. Vậy code chạy sẽ lấy dữ liệu của ô nào và điền vào Cột nào (Cột I=5 lần;J=4 lần,...N=0 lần) hay là không lấy ô nào cả.
Nhìn chung là bạn cứ mô tả thật kỹ kết quả mong muốn, có thể giả định kết quả (làm tay) 1-2 trường hợp và upfile lên. Có như vậy nhiều người trên diễn đàn tiếp cận với yêu cầu của bạn họ mới dễ hình dung ra để code giúp bạn chứ (hoặc chí ít thì cũng có thể góp ý hoặc thêm phương án, giải pháp khác...), chứ còn không cứ vừa code vừa đoán ý thì ....
 
Sao mình thấy số 32 nằm ở chô khoanh đỏ này có đúng không nhỉ?
Có khi nào có trường hợp ở giữa không bôi màu không nhỉ
View attachment 272760
Sao mình thấy số 32 nằm ở chô khoanh đỏ này có đúng không nhỉ?
Có khi nào có trường hợp ở giữa không bôi màu không nhỉ
View attachment 272760
Nhìn chung là mặc dù chưa hiểu hết ý bạn ấy ở đề bài ở #23 tuy nhiên cứ code theo ý hiểu của mình.
Bạn giúp bạn ấy đi, có gí đăng lên cho mình học hỏi thêm
Bài đã được tự động gộp:

Anh lại khiêm tốn quá rồi
Tôi nói thật lòng mình mà. nhiều bài tôi cứ ngỡ là mình hiểu ý chủ thớt và nghĩ là làm được. đến khi làm xong định đăng lên trả bài, thì thấy đã có người trả lời, đọc bài và chạy code của họ mới biết mình đã đi sai hướng ==>thuật toán sai==> kết chưa được toàn vẹn.
 
Lần chỉnh sửa cuối:
Bạn giúp bạn ấy đi, có gí đăng lên cho mình học hỏi thêm
Hihi. Em biết gì đâu anh
Góp vui với code rùa này. chắc tốc độ không bằng mảng được. Áp dụng cho câu đầu. Còn yêu cầu bài 23 em cũng chưa biết thớt muốn gì
Mã:
Sub ABC()
Dim i&, j&, iR&, iC&, K&
With Sheet1
    .Range("I2:N10000").ClearContents
    iR = .Range("A" & Rows.Count).End(xlUp).Row
    For i = 2 To iR
        K = 0
        iC = .Cells(i, Columns.Count).End(1).Column
        For j = 1 To iC
            If .Cells(i, j) <> Empty Then
                If .Cells(i, j).Interior.Color <> vbYellow Then
                    .Cells(i, 14 - K).Value = .Cells(i, iC).Value
                Else
                    K = K + 1
                End If
            End If
        Next
    Next
End With
End Sub
 
Lần chỉnh sửa cuối:
Nhìn chung là mặc dù chưa hiểu hết ý bạn ấy ở đề bài ở #23 tuy nhiên cứ code theo ý hiểu của mình.
Bạn giúp bạn ấy đi, có gí đăng lên cho mình học hỏi thêm
Bài đã được tự động gộp:


Tôi nói thật lòng mình mà. nhiều bài tôi cứ ngỡ là mình hiểu ý chủ thớt và nghĩ là làm được. đến khi làm xong định đăng lên trả bài, thì thấy đã có người trả lời, đọc bài và chạy code của họ mới biết mình đã đi sai hướng ==>thuật toán sai==> kết chưa được toàn vẹn.
Dạ thành thật mong hai Anh bỏ qua cho. Do cách hành văn lủng củng nên khó diễn đạt làm phiền đến các Anh nhiều lần. Mong hai Anh giúp thêm lần này ak! Nội dung cụ thể em đã ghi trong file đính kèm ak!
Rất mong sự giúp đỡ của các Anh!
 

File đính kèm

Dạ thành thật mong hai Anh bỏ qua cho. Do cách hành văn lủng củng nên khó diễn đạt làm phiền đến các Anh nhiều lần. Mong hai Anh giúp thêm lần này ak! Nội dung cụ thể em đã ghi trong file đính kèm ak!
Rất mong sự giúp đỡ của các Anh!
Giải thích lòng vòng thêm rối, dựa vào dữ liệu và kết quả trong file
Mã:
Sub ABC()
  Dim a$(), b$(1 To 1, 1 To 6), rng As Range, sRow&, i&, j&, C&
  Set rng = Sheet1.Range("A4:I" & Sheet1.Range("A" & Rows.Count).End(xlUp).Row)
  sRow = rng.Rows.Count
  ReDim a(1 To sRow, 1 To 6)
  For i = 1 To sRow
    C = 6
    For j = 1 To 8
      If rng(i, j).Interior.Color = vbYellow Then C = C - 1
      If rng(i, j + 1) = Empty Then
        a(i, C) = rng(i, j)
        If InStr(1, b(1, C), a(i, C)) = 0 Then
          If Len(b(1, C)) Then b(1, C) = b(1, C) & "," & a(i, C) Else b(1, C) = a(i, C)
        End If
        Exit For
      End If
    Next j
  Next i
  Range("I2:T10000").Clear
  Sheet1.Range("I4").Resize(sRow, 6) = a
  Sheet1.Range("P2").Resize(, 5) = b
End Sub
Dữ liệu khác có thể tèo
 

File đính kèm

Giải thích lòng vòng thêm rối, dựa vào dữ liệu và kết quả trong file
Mã:
Sub ABC()
  Dim a$(), b$(1 To 1, 1 To 6), rng As Range, sRow&, i&, j&, C&
  Set rng = Sheet1.Range("A4:I" & Sheet1.Range("A" & Rows.Count).End(xlUp).Row)
  sRow = rng.Rows.Count
  ReDim a(1 To sRow, 1 To 6)
  For i = 1 To sRow
    C = 6
    For j = 1 To 8
      If rng(i, j).Interior.Color = vbYellow Then C = C - 1
      If rng(i, j + 1) = Empty Then
        a(i, C) = rng(i, j)
        If InStr(1, b(1, C), a(i, C)) = 0 Then
          If Len(b(1, C)) Then b(1, C) = b(1, C) & "," & a(i, C) Else b(1, C) = a(i, C)
        End If
        Exit For
      End If
    Next j
  Next i
  Range("I2:T10000").Clear
  Sheet1.Range("I4").Resize(sRow, 6) = a
  Sheet1.Range("P2").Resize(, 5) = b
End Sub
Dữ liệu khác có thể tèo
Kính nể, code vùa ngắn mà kết quả như ý.
Tôi cũng đã làm lại cho bạn ấy cũng ra kết quả nhung code hơi dài.
Dạ thành thật mong hai Anh bỏ qua cho. Do cách hành văn lủng củng nên khó diễn đạt làm phiền đến các Anh nhiều lần. Mong hai Anh giúp thêm lần này ak! Nội dung cụ thể em đã ghi trong file đính kèm ak!
Rất mong sự giúp đỡ của các Anh!
Bạn thử xem code củ chuối này nhé.
Mã:
Option Explicit

Sub Mau()
Dim i&, j&, t&, k&, tt&, Lr, Col&
Dim rng As Range, Sh As Worksheet, Ketqua As Range
Dim KQ(), SoLan(), NOI As String
Dim Dic As Object, Key

Set Sh = Sheet1
'Set Ketqua = Sh.[U1]
Set rng = Sh.Range("A4").CurrentRegion
Lr = rng.Rows.Count: Col = rng.Columns.Count
ReDim KQ(1 To Lr, 1 To Col)
For i = 1 To Lr
t = 0: k = 0: NOI = Empty
    For j = 1 To Col
        If rng(i, j) <> Empty Then
            k = k + 1:
            If rng(i, j).Interior.Color = vbYellow Then t = t + 1
            If rng(i, j).Interior.Color <> vbYellow Then
                If NOI = Empty Then NOI = rng(i, j) Else NOI = NOI & ";" & rng(i, j)
            End If
        Else: Exit For
        End If
    Next j
        If t = 0 Then KQ(i, Col) = NOI Else KQ(i, Col - t) = rng(i, k)
Next i
ReDim SoLan(1 To 1, 1 To UBound(KQ))
For i = 1 To UBound(KQ, 2) - 1
Set Dic = CreateObject("Scripting.Dictionary")
    For j = 1 To UBound(KQ, 1)
        If KQ(j, i) <> Empty Then
            Key = KQ(j, i)
            If Not Dic.Exists(Key) Then
            tt = tt + 1: Dic.Add (Key), tt
                If SoLan(1, i) = Empty Then SoLan(1, i) = Key Else SoLan(1, i) = SoLan(1, i) & ";" & Key
            End If
        End If
    Next j
    Set Dic = Nothing
Next i
Sh.[I2].Resize(1, i) = SoLan
Sh.[I4].Resize(Lr, Col) = KQ
End Sub
Khuyên bạn nên sử dụng code của Anh @HieuCD
 
Giải thích lòng vòng thêm rối, dựa vào dữ liệu và kết quả trong file
Mã:
Sub ABC()
  Dim a$(), b$(1 To 1, 1 To 6), rng As Range, sRow&, i&, j&, C&
  Set rng = Sheet1.Range("A4:I" & Sheet1.Range("A" & Rows.Count).End(xlUp).Row)
  sRow = rng.Rows.Count
  ReDim a(1 To sRow, 1 To 6)
  For i = 1 To sRow
    C = 6
    For j = 1 To 8
      If rng(i, j).Interior.Color = vbYellow Then C = C - 1
      If rng(i, j + 1) = Empty Then
        a(i, C) = rng(i, j)
        If InStr(1, b(1, C), a(i, C)) = 0 Then
          If Len(b(1, C)) Then b(1, C) = b(1, C) & "," & a(i, C) Else b(1, C) = a(i, C)
        End If
        Exit For
      End If
    Next j
  Next i
  Range("I2:T10000").Clear
  Sheet1.Range("I4").Resize(sRow, 6) = a
  Sheet1.Range("P2").Resize(, 5) = b
End Sub
Dữ liệu khác có thể tèo
Thật là kết quả thật ngoài mong đợi, một lần nữa xin được Cám ơn Anh Hiếu CD và Anh HuongTCKT cũng như All mọi người đã giúp đỡ. Code anh Hiếu em cũng hay vọc trên diễn đàn. Bác hay có sở thích đặt tên sub là ABC. Chúc các Anh một ngày nghỉ cuối tuần vui vẻ bên người thân và gia đình!
Bài đã được tự động gộp:

Kính nể, code vùa ngắn mà kết quả như ý.
Tôi cũng đã làm lại cho bạn ấy cũng ra kết quả nhung code hơi dài.

Bạn thử xem code củ chuối này nhé.
Mã:
Option Explicit

Sub Mau()
Dim i&, j&, t&, k&, tt&, Lr, Col&
Dim rng As Range, Sh As Worksheet, Ketqua As Range
Dim KQ(), SoLan(), NOI As String
Dim Dic As Object, Key

Set Sh = Sheet1
'Set Ketqua = Sh.[U1]
Set rng = Sh.Range("A4").CurrentRegion
Lr = rng.Rows.Count: Col = rng.Columns.Count
ReDim KQ(1 To Lr, 1 To Col)
For i = 1 To Lr
t = 0: k = 0: NOI = Empty
    For j = 1 To Col
        If rng(i, j) <> Empty Then
            k = k + 1:
            If rng(i, j).Interior.Color = vbYellow Then t = t + 1
            If rng(i, j).Interior.Color <> vbYellow Then
                If NOI = Empty Then NOI = rng(i, j) Else NOI = NOI & ";" & rng(i, j)
            End If
        Else: Exit For
        End If
    Next j
        If t = 0 Then KQ(i, Col) = NOI Else KQ(i, Col - t) = rng(i, k)
Next i
ReDim SoLan(1 To 1, 1 To UBound(KQ))
For i = 1 To UBound(KQ, 2) - 1
Set Dic = CreateObject("Scripting.Dictionary")
    For j = 1 To UBound(KQ, 1)
        If KQ(j, i) <> Empty Then
            Key = KQ(j, i)
            If Not Dic.Exists(Key) Then
            tt = tt + 1: Dic.Add (Key), tt
                If SoLan(1, i) = Empty Then SoLan(1, i) = Key Else SoLan(1, i) = SoLan(1, i) & ";" & Key
            End If
        End If
    Next j
    Set Dic = Nothing
Next i
Sh.[I2].Resize(1, i) = SoLan
Sh.[I4].Resize(Lr, Col) = KQ
End Sub
Khuyên bạn nên sử dụng code của Anh @HieuCD
code này em sử dụng thấy nó bị sai anh ak? nhảy với cộng số lần sai
 
Lần chỉnh sửa cuối:

File đính kèm

Dạ em xin gửi lại file anh check ak! em comment ở trong file đó ak!
Trân trọng!
Đó là nó xếp không đúng với cột tiêu đề thôi. (do số cột lớn nhất là 8 mà số ô có màu trong các dòng lớn nhất là 5. Do vậy Cột lớn nhất - (số ô có màu liên tiếp là 5 +1 Ô không có màu cuối cùng=8) =2 .do vậy khi dán kết quả xuống sheet nó bị chệch 2 cột.
Nghĩ mãi mà không biết làm cách nào.

Có chơi kiểu xếp là Không có màu , 1 lần , 2 ,3,4,5,6....lần không?Số lần ô tô màu trong dòng có thể không hạn chế (10,100, hoặc một số n lần nào đó) ...Nếu xếp theo kiểu như tôi trình bày thì code dễ hơn, chính xác hơn. Bạn thêm dữ liệu, chạy code và kiểm tra lại kết quả Ở I2:...
Nếu trong dải ô ấy có n ô được tô màu và có 1 hoặc 2 ô không được tô màu xen kẽ các ô tô màu thì lấy kết quả thế nào, tính liên tiếp là mấy hay vẫn tính là n lần?
 

File đính kèm

Đó là nó xếp không đúng với cột tiêu đề thôi. (do số cột lớn nhất là 8 mà số ô có màu trong các dòng lớn nhất là 5. Do vậy Cột lớn nhất - (số ô có màu liên tiếp là 5 +1 Ô không có màu cuối cùng=8) =2 .do vậy khi dán kết quả xuống sheet nó bị chệch 2 cột.
Nghĩ mãi mà không biết làm cách nào.

Có chơi kiểu xếp là Không có màu , 1 lần , 2 ,3,4,5,6....lần không?Số lần ô tô màu trong dòng có thể không hạn chế (10,100, hoặc một số n lần nào đó) ...Nếu xếp theo kiểu như tôi trình bày thì code dễ hơn, chính xác hơn. Bạn thêm dữ liệu, chạy code và kiểm tra lại kết quả Ở I2:...
Nếu trong dải ô ấy có n ô được tô màu và có 1 hoặc 2 ô không được tô màu xen kẽ các ô tô màu thì lấy kết quả thế nào, tính liên tiếp là mấy hay vẫn tính là n lần?
Cám ơn anh rất nhiều. Ý Anh hỏi tính theo số ô không được tô màu em cũng muốn tính xem số ô không được tô màu từ 1 đến n lần như ô được tô màu ak. Phiền Anh có thể code thêm phần những ô không được tô màu từ 1 đến n lần. Ta tính thêm cho trường hợp ngược lại với bài toán tính ô có màu Anh ak!
 
Cám ơn anh rất nhiều. Ý Anh hỏi tính theo số ô không được tô màu em cũng muốn tính xem số ô không được tô màu từ 1 đến n lần như ô được tô màu ak. Phiền Anh có thể code thêm phần những ô không được tô màu từ 1 đến n lần. Ta tính thêm cho trường hợp ngược lại với bài toán tính ô có màu Anh ak!
Em đã chạy code và rất ngưỡng mộ Bác. ở đây code chạy rất ok. Nhưng với trường hợp ở những ô không có màu thì em thấy Anh viết code tính cộng cả các hàng bên trên không có màu. Mong muốn của em là mong Anh sửa giúp em với các ô không có màu từ 1 đến N cũng giống như với ô đã được tô màu ak!( Tính thêm với các ô không được bôi màu tương tự như với ô đã được bôi màu đó anh). Em đã ghi chú trong file đính kèm ak!
Kính mong Anh chiếu cố giúp cho.
Trân trọng/
 

File đính kèm

Em đã chạy code và rất ngưỡng mộ Bác. ở đây code chạy rất ok. Nhưng với trường hợp ở những ô không có màu thì em thấy Anh viết code tính cộng cả các hàng bên trên không có màu. Mong muốn của em là mong Anh sửa giúp em với các ô không có màu từ 1 đến N cũng giống như với ô đã được tô màu ak!( Tính thêm với các ô không được bôi màu tương tự như với ô đã được bôi màu đó anh). Em đã ghi chú trong file đính kèm ak!
Kính mong Anh chiếu cố giúp cho.
Trân trọng/
Thành thật xin lỗi Anh! đọc nội dung Anh viết em mừng quá. file vừa rồi e gửi thiếu nội dung nên lần này em chỉnh sửa lại theo câu hỏi của Anh đã ghi trong file. Quả thật Bác thiệt tài đọc luôn được ý trong đầu em vậy. Em xin gửi lại file Anh chiếu cố giúp cho.
Cám ơn Anh đã quan tâm!
Trân trọng/
 

File đính kèm

Giải thích lòng vòng thêm rối, dựa vào dữ liệu và kết quả trong file
Mã:
Sub ABC()
  Dim a$(), b$(1 To 1, 1 To 6), rng As Range, sRow&, i&, j&, C&
  Set rng = Sheet1.Range("A4:I" & Sheet1.Range("A" & Rows.Count).End(xlUp).Row)
  sRow = rng.Rows.Count
  ReDim a(1 To sRow, 1 To 6)
  For i = 1 To sRow
    C = 6
    For j = 1 To 8
      If rng(i, j).Interior.Color = vbYellow Then C = C - 1
      If rng(i, j + 1) = Empty Then
        a(i, C) = rng(i, j)
        If InStr(1, b(1, C), a(i, C)) = 0 Then
          If Len(b(1, C)) Then b(1, C) = b(1, C) & "," & a(i, C) Else b(1, C) = a(i, C)
        End If
        Exit For
      End If
    Next j
  Next i
  Range("I2:T10000").Clear
  Sheet1.Range("I4").Resize(sRow, 6) = a
  Sheet1.Range("P2").Resize(, 5) = b
End Sub
Dữ liệu khác có thể

Đó là nó xếp không đúng với cột tiêu đề thôi. (do số cột lớn nhất là 8 mà số ô có màu trong các dòng lớn nhất là 5. Do vậy Cột lớn nhất - (số ô có màu liên tiếp là 5 +1 Ô không có màu cuối cùng=8) =2 .do vậy khi dán kết quả xuống sheet nó bị chệch 2 cột.
Nghĩ mãi mà không biết làm cách nào.

Có chơi kiểu xếp là Không có màu , 1 lần , 2 ,3,4,5,6....lần không?Số lần ô tô màu trong dòng có thể không hạn chế (10,100, hoặc một số n lần nào đó) ...Nếu xếp theo kiểu như tôi trình bày thì code dễ hơn, chính xác hơn. Bạn thêm dữ liệu, chạy code và kiểm tra lại kết quả Ở I2:...
Nếu trong dải ô ấy có n ô được tô màu và có 1 hoặc 2 ô không được tô màu xen kẽ các ô tô màu thì lấy kết quả thế nào, tính liên tiếp là mấy hay vẫn tính là n lần?
Em có thêm một vấn đề nữa mong Bác giúp ak!
Tình hình là em có chuỗi muốn lọc và loại kí tự lặp nhiều lần chỉ giữ lại lần lặp đầu sau đó đếm số lần kí tự có trong chuỗi liệt kê sang cột riêng. Vấn đề nữa là cộng tịnh tiến theo hàng các số tự nhiên theo qui luật một hàng cho trước. Nội dung em ghi trong file đính kèm.
Kính mong Anh bớt chút thời gian giúp cho!
Trân trọng/
 

File đính kèm

Em có thêm một vấn đề nữa mong Bác giúp ak!
Tình hình là em có chuỗi muốn lọc và loại kí tự lặp nhiều lần chỉ giữ lại lần lặp đầu sau đó đếm số lần kí tự có trong chuỗi liệt kê sang cột riêng. Vấn đề nữa là cộng tịnh tiến theo hàng các số tự nhiên theo qui luật một hàng cho trước. Nội dung em ghi trong file đính kèm.
Kính mong Anh bớt chút thời gian giúp cho!
Trân trọng/
cái này là bài mới rồi mà. bạn nên lập chủ đề mới
 
Thành thật xin lỗi Anh! đọc nội dung Anh viết em mừng quá. file vừa rồi e gửi thiếu nội dung nên lần này em chỉnh sửa lại theo câu hỏi của Anh đã ghi trong file. Quả thật Bác thiệt tài đọc luôn được ý trong đầu em vậy. Em xin gửi lại file Anh chiếu cố giúp cho.
Cám ơn Anh đã quan tâm!
Trân trọng/
Thế này chăng?
Xem file
 

File đính kèm

Em có thêm một vấn đề nữa mong Bác giúp ak!
Tình hình là em có chuỗi muốn lọc và loại kí tự lặp nhiều lần chỉ giữ lại lần lặp đầu sau đó đếm số lần kí tự có trong chuỗi liệt kê sang cột riêng. Vấn đề nữa là cộng tịnh tiến theo hàng các số tự nhiên theo qui luật một hàng cho trước. Nội dung em ghi trong file đính kèm.
Kính mong Anh bớt chút thời gian giúp cho!
Trân trọng/
Chạy 2 code . . .
Mã:
Option Explicit
Sub Dem()
  Dim arr(), S, res(), str$, tmp$, t$, a$, d$
  Dim sR&, i&, k&, j&, N&, fC&, c&
  Const deli$ = ",.;:-"
  With Sheet1
    arr = .Range("A2", .Range("A2").End(xlDown)).Value
  End With
  sR = UBound(arr)
  ReDim res(1 To sR, 1 To 3)
  For i = 1 To sR
    str = Replace(arr(i, 1), " ", "") & ","
    N = Len(str)
    fC = 1
    k = 0
    tmp = "|"
    a = Empty: d = Empty
    For j = 1 To N
      c = InStr(1, deli, Mid(str, j, 1))
      If c > 0 Then
        t = Mid(str, fC, j - fC)
        If InStr(1, tmp, "|" & t & "|") = 0 Then
          k = k + 1
          tmp = tmp & t & "|"
          a = a & d & t
          d = Mid(deli, c, 1)
        End If
        fC = j + 1
      End If
    Next j
    If a = Empty Then res(i, 1) = str Else res(i, 1) = a
    res(i, 2) = k
  Next i
  Sheet1.Range("B2").Resize(sR).NumberFormat = "@"
  Sheet1.Range("B2").Resize(sR, 2) = res
End Sub

Sub Them()
  Dim arr(), res(), sR&, sC&, i&, j&

  arr = Sheet1.Range("E2:N2").Resize(10).Value
  sR = UBound(arr, 1): sC = UBound(arr, 2)
  For j = 1 To sC
    For i = 2 To sR
      If arr(i - 1, j) = 9 Then arr(i, j) = 0 Else arr(i, j) = arr(i - 1, j) + 1
    Next i
  Next j
  Sheet1.Range("E2:N2").Resize(10).Value = arr
End Sub
 

File đính kèm

Chạy 2 code . . .
Mã:
Option Explicit
Sub Dem()
  Dim arr(), S, res(), str$, tmp$, t$, a$, d$
  Dim sR&, i&, k&, j&, N&, fC&, c&
  Const deli$ = ",.;:-"
  With Sheet1
    arr = .Range("A2", .Range("A2").End(xlDown)).Value
  End With
  sR = UBound(arr)
  ReDim res(1 To sR, 1 To 3)
  For i = 1 To sR
    str = Replace(arr(i, 1), " ", "") & ","
    N = Len(str)
    fC = 1
    k = 0
    tmp = "|"
    a = Empty: d = Empty
    For j = 1 To N
      c = InStr(1, deli, Mid(str, j, 1))
      If c > 0 Then
        t = Mid(str, fC, j - fC)
        If InStr(1, tmp, "|" & t & "|") = 0 Then
          k = k + 1
          tmp = tmp & t & "|"
          a = a & d & t
          d = Mid(deli, c, 1)
        End If
        fC = j + 1
      End If
    Next j
    If a = Empty Then res(i, 1) = str Else res(i, 1) = a
    res(i, 2) = k
  Next i
  Sheet1.Range("B2").Resize(sR).NumberFormat = "@"
  Sheet1.Range("B2").Resize(sR, 2) = res
End Sub

Sub Them()
  Dim arr(), res(), sR&, sC&, i&, j&

  arr = Sheet1.Range("E2:N2").Resize(10).Value
  sR = UBound(arr, 1): sC = UBound(arr, 2)
  For j = 1 To sC
    For i = 2 To sR
      If arr(i - 1, j) = 9 Then arr(i, j) = 0 Else arr(i, j) = arr(i - 1, j) + 1
    Next i
  Next j
  Sheet1.Range("E2:N2").Resize(10).Value = arr
End Sub
Thực lòng xin cảm ơn Thầy nhiều ak!, Em Kính chúc Thầy luôn mạnh khoẻ và thành công.
Trân trọng/
Bài đã được tự động gộp:

Cái sub dem đúng là tuyệt. Cám ơn thầy
Thầy xử lí luôn được cả các kí tự :," ;, ." vv...và vv. Thầy đúng là quá giỏi.!
Bài đã được tự động gộp:

Cám ơn Anh đã hướng dẫn ak!
 
Lần chỉnh sửa cuối:
Cám ơn Anh ak! Code của Anh quá tuyệt vời, cuối cùng vượt ngoài mong đợi của em. Thành thật xin lỗi vì phiền anh nhiều vì văn phạm lủng củng không nói nên được nội dụng làm anh mất thời gian viết đi viết lại. Một lần nữa gửi lời chúc đến Anh và gia đình có ngày 8.3 vui vẻ và hạnh phúc!
Trân trọng/
 
Cám ơn Anh nhiều nhiều! Tuy nhiên khi chạy code chưa đúng với nội dung mong muốn và định dạng là text chứ không phải là number vì vậy mong Anh chỉnh giúp. Nội dung mong muốn sửa em ghi trong file ak!
 

File đính kèm

Chạy 2 code . . .
Mã:
Option Explicit
Sub Dem()
  Dim arr(), S, res(), str$, tmp$, t$, a$, d$
  Dim sR&, i&, k&, j&, N&, fC&, c&
  Const deli$ = ",.;:-"
  With Sheet1
    arr = .Range("A2", .Range("A2").End(xlDown)).Value
  End With
  sR = UBound(arr)
  ReDim res(1 To sR, 1 To 3)
  For i = 1 To sR
    str = Replace(arr(i, 1), " ", "") & ","
    N = Len(str)
    fC = 1
    k = 0
    tmp = "|"
    a = Empty: d = Empty
    For j = 1 To N
      c = InStr(1, deli, Mid(str, j, 1))
      If c > 0 Then
        t = Mid(str, fC, j - fC)
        If InStr(1, tmp, "|" & t & "|") = 0 Then
          k = k + 1
          tmp = tmp & t & "|"
          a = a & d & t
          d = Mid(deli, c, 1)
        End If
        fC = j + 1
      End If
    Next j
    If a = Empty Then res(i, 1) = str Else res(i, 1) = a
    res(i, 2) = k
  Next i
  Sheet1.Range("B2").Resize(sR).NumberFormat = "@"
  Sheet1.Range("B2").Resize(sR, 2) = res
End Sub

Sub Them()
  Dim arr(), res(), sR&, sC&, i&, j&

  arr = Sheet1.Range("E2:N2").Resize(10).Value
  sR = UBound(arr, 1): sC = UBound(arr, 2)
  For j = 1 To sC
    For i = 2 To sR
      If arr(i - 1, j) = 9 Then arr(i, j) = 0 Else arr(i, j) = arr(i - 1, j) + 1
    Next i
  Next j
  Sheet1.Range("E2:N2").Resize(10).Value = arr
End Sub
Thầy ơi cứu em!
Code lần trước Thầy viết giúp em nhưng khi em chạy nảy sinh một số vấn đề ak. Cụ thể trong code Thầy viết đem cộng liệt kê toàn bộ hàng có bôi màu và không loại đi ô bị ngắt quãng trong hàng. Mong muốn cụ thể nhờ Thầy chỉnh lại em viết trong file đính kèm.
Mong Thầy giúp em!
Trân trong/
 

File đính kèm

Thầy ơi cứu em!
Code lần trước Thầy viết giúp em nhưng khi em chạy nảy sinh một số vấn đề ak. Cụ thể trong code Thầy viết đem cộng liệt kê toàn bộ hàng có bôi màu và không loại đi ô bị ngắt quãng trong hàng. Mong muốn cụ thể nhờ Thầy chỉnh lại em viết trong file đính kèm.
Mong Thầy giúp em!
Trân trong/
Dữ liệu khác code phải khác nhiều. Gởi file với cấu trúc dữ liệu thật, dữ liệu có thể thay thế bằng dữ liệu giả định nếu muốn bảo mật, để viết code 1 lần cuối
 
Cám ơn Anh nhiều nhiều! Tuy nhiên khi chạy code chưa đúng với nội dung mong muốn và định dạng là text chứ không phải là number vì vậy mong Anh chỉnh giúp. Nội dung mong muốn sửa em ghi trong file ak!
Bạn trình bày trong file thực tình tôi không hiểu gì cả.
Bạn viết ".....Ví dụ ô D2 số (05) vẫn liệt kê là 3 màu liên tục. ở đây phép so sánh em cần là tính từ ô được có màu liên tục nhiều nhất tính lùi lại. ví dụ ở cột E4 thì phép so sánh được tính đúng là 1 mới là đúng. vì ô f4 (09) tính lùi về bên trái có màu là số (07) và nó bị ngắt quãng là ô d4(05) không tô màu nên là nếu liệt kê đúng phải là 1 màu liên tục ...."
Trong khi trong comment bạn viết : "...vị trí ô này ko có màu thì chỉ liệt kê 3 màu liên tục ak! Só 05 sẽ được tính là 3 màu liên tục. Tham chiếu cột ứng với nó để tính với ô không có màu đối với trường hợp tính ô không có màu.". Vậy thì là điếm số ô có màu liên tục hay là gì? và nếu đúng thế ghi kết quả đếm hay ghi dữ liệu nào vào ô tương ứng.
Và bạn viết ".... Lưu ý không tính nếu như hàng đó bị ngắt quãng hay đúng hơn là phép tính liên tục chỉ tham chiếu từ bên phải qua trái từ cột f4 đến a4 ví dụ nếu gặp e4 có màu rồi d4 không có màu thì tính là 1 màu liên tục. tương tự như hàng F7 tính liên tục nếu đúng thì là 3 màu liên tục mới đúng ý bởi hàng đó bị ngắt quãng bởi ô b7(02)....." Nghĩa là chỉ lấy một giá trị (số đếm được hay dữ liệu 1 ô ), còn không quan tâm đến các số điếm được các ô có màu sau đó của hàng đó (trương trường hợp số ô có màu và không màu xen kẽ không có quy luật)
Ở bài #23 bạn đửa ra đề bài là " .....mong muốn của e là viết code lấy 01 con số nằm ở ô cuối cùng của hàng đã được tô màu và tách sang cột riêng biệt".
Cứ như thế này thì có lẽ bạn phải chờ lâu lâu mới có đáp án.
Tôi đã phải là đoán mò: Thế này chăng? ở bài#48 khi gửi trả đáp án cho bạn.
Thay vì giải thích, bạn cứ gửi file có mô tả cách lấy dữ liệu và điền kết quả mong muốn (chỉ cần 1 số dòng ). Chứ cứ để tình trạng mỗi người mỗi hướng này thì bao giờ mới được. Tôi đã nói rồi: "Tôi Không phải là người tinh anh như người ta" rồi mà.
 
Bạn trình bày trong file thực tình tôi không hiểu gì cả.
Bạn viết ".....Ví dụ ô D2 số (05) vẫn liệt kê là 3 màu liên tục. ở đây phép so sánh em cần là tính từ ô được có màu liên tục nhiều nhất tính lùi lại. ví dụ ở cột E4 thì phép so sánh được tính đúng là 1 mới là đúng. vì ô f4 (09) tính lùi về bên trái có màu là số (07) và nó bị ngắt quãng là ô d4(05) không tô màu nên là nếu liệt kê đúng phải là 1 màu liên tục ...."
Trong khi trong comment bạn viết : "...vị trí ô này ko có màu thì chỉ liệt kê 3 màu liên tục ak! Só 05 sẽ được tính là 3 màu liên tục. Tham chiếu cột ứng với nó để tính với ô không có màu đối với trường hợp tính ô không có màu.". Vậy thì là điếm số ô có màu liên tục hay là gì? và nếu đúng thế ghi kết quả đếm hay ghi dữ liệu nào vào ô tương ứng.
Và bạn viết ".... Lưu ý không tính nếu như hàng đó bị ngắt quãng hay đúng hơn là phép tính liên tục chỉ tham chiếu từ bên phải qua trái từ cột f4 đến a4 ví dụ nếu gặp e4 có màu rồi d4 không có màu thì tính là 1 màu liên tục. tương tự như hàng F7 tính liên tục nếu đúng thì là 3 màu liên tục mới đúng ý bởi hàng đó bị ngắt quãng bởi ô b7(02)....." Nghĩa là chỉ lấy một giá trị (số đếm được hay dữ liệu 1 ô ), còn không quan tâm đến các số điếm được các ô có màu sau đó của hàng đó (trương trường hợp số ô có màu và không màu xen kẽ không có quy luật)
Ở bài #23 bạn đửa ra đề bài là " .....mong muốn của e là viết code lấy 01 con số nằm ở ô cuối cùng của hàng đã được tô màu và tách sang cột riêng biệt".
Cứ như thế này thì có lẽ bạn phải chờ lâu lâu mới có đáp án.
Tôi đã phải là đoán mò: Thế này chăng? ở bài#48 khi gửi trả đáp án cho bạn.
Thay vì giải thích, bạn cứ gửi file có mô tả cách lấy dữ liệu và điền kết quả mong muốn (chỉ cần 1 số dòng ). Chứ cứ để tình trạng mỗi người mỗi hướng này thì bao giờ mới được. Tôi đã nói rồi: "Tôi Không phải là người tinh anh như người ta" rồi mà.
Dạ! Thật lòng không biết nói gì ngoài lời cảm kích ngưỡng mộ Anh, em xin gửi lại file với nội dung mong muốn. Anh bớt chút thời gian xem qua và code giúp.
Trân trọng/
 

File đính kèm

Úi chà. Hóa ra là nghề chọn những con số thần kỳ.

Thấy bạn này tâm sự công việc không dùng tới Excel nhưng lại đam mê viết code. Giờ thì đã hiểu động lực đam mê là gì.

View attachment 272911
Dạ cái này nó ứng dụng nhiều đó anh, file giả lập về màu kiểu liệt kê màu những hàng có ô liên tục bôi màu kiểu đánh dấu ak.
 
Dữ liệu khác code phải khác nhiều. Gởi file với cấu trúc dữ liệu thật, dữ liệu có thể thay thế bằng dữ liệu giả định nếu muốn bảo mật, để viết code 1 lần cuối
Dạ em gửi lại anh file. Nội dung mong muốn em viết ở trong file ak!
Bài đã được tự động gộp:

Dạ em gửi lại anh file. Nội dung mong muốn em viết ở trong file ak!
 

File đính kèm

Lần chỉnh sửa cuối:
Úi chà. Hóa ra là nghề chọn những con số thần kỳ.

Thấy bạn này tâm sự công việc không dùng tới Excel nhưng lại đam mê viết code. Giờ thì đã hiểu động lực đam mê là gì.
...
Đam mê là nhờ làm giùm sao? Chắc là định nghĩa mới. Hồi nào giờ tôi cứ ngỡ người đam mê thì tự làm lấy, chỉ hỏi một vài chỗ vướng mắc.

Động lực là cơn ghiền code của quý vị. Cứ thấy hỏi code là làm tới.

Thớt biết đặc điểm này của dân GPE cho nên cứ thả thẳng ga. Hết ý tưởng này đến sáng kiến khác.

Chú riêng cho tác giả bài #59: kiểu hành động thì giống như một "người quen" trước đây. Chỉ là cách ăn nói thì chưa thấy giống. Nhất là "người quen" kia không có tật xổ Tây.
 
Dạ! Thật lòng không biết nói gì ngoài lời cảm kích ngưỡng mộ Anh, em xin gửi lại file với nội dung mong muốn. Anh bớt chút thời gian xem qua và code giúp.
Trân trọng/
Phải chăng thế này? Hy vọng lần này đúng ý và không phải làm lại.
Nếu bạn ứng dụng nó vào việc tính lô, đề (hay đại loại là đánh bạc..), thì hãy tìm và liên hệ đến đội ngũ làm tín dụng đen, bảo họ giúp nhé. Tin chắc là nhận được sự giúp đỡ vô bờ bến. hihi
 

File đính kèm

Phải chăng thế này? Hy vọng lần này đúng ý và không phải làm lại.
Nếu bạn ứng dụng nó vào việc tính lô, đề (hay đại loại là đánh bạc..), thì hãy tìm và liên hệ đến đội ngũ làm tín dụng đen, bảo họ giúp nhé. Tin chắc là nhận được sự giúp đỡ vô bờ bến. hihi
Cám ơn Anh.
Phải chăng thế này? Hy vọng lần này đúng ý và không phải làm lại.
Nếu bạn ứng dụng nó vào việc tính lô, đề (hay đại loại là đánh bạc..), thì hãy tìm và liên hệ đến đội ngũ làm tín dụng đen, bảo họ giúp nhé. Tin chắc là nhận được sự giúp đỡ vô bờ bến. hihi
Cám ơn Anh đã chiếu cố! Nhưng khi chạy code thì lỗi báo
ReDim S(1 To 100)
For i = 4 To Lr
t = t + 1 .
Em dốt vụ VBA nên không biết chỉnh sao ạ!
 
Mình đoán mò thôi chứ vụ này cũng không xem file nữa.
"Em ngồi im xem các tiền bối để học hỏi vậy" cũng tương đương "Tọa sơn quan hổ chén"
Vào xem cũng đươc mà anh. Nhặt nhạnh được tý kiến thức nào thì hay tí ấy. Trong này toàn thành viên sịn mà em ngưỡng mộ ấy. Hihi.
 
Dựa vào code của thầy @HieuCD. Mình có chỉnh sửa theo ý muốn của chủ topic. Ai đó có thể chỉ giúp cách tối ưu hoặc giản số lần duyệt với ạ
Mã:
Sub ABC()
Application.ScreenUpdating = False
Dim a$(), b$(), Rng As Range, sRow&, i&, j&, C&, sCol&, x$(), y$()
Set Rng = Sheet1.Range("A4").CurrentRegion
sRow = Rng.Rows.Count
  sCol = Rng.Columns.Count
  ReDim a(1 To sRow, 1 To sCol - 1)
  ReDim x(1 To sRow, 1 To sCol - 1)
  ReDim b(1 To 2, 1 To sCol - 1)
  ReDim y(1 To 2, 1 To sCol - 1)
  For j = sCol - 1 To 1 Step -1
    b(1, j) = "Lien tuc co mau lien tiep " & sCol - j
    y(1, j) = "Khong co mau lien tiep " & sCol - j
  Next
  For i = 1 To sRow
    C = sCol - 1
    For j = sCol - 1 To 1 Step -1
        If Rng(i, sCol - 1).Interior.Color = vbYellow Then
            If Rng(i, j).Interior.Color = vbYellow Then C = C - 1
            If Rng(i, j).Interior.Color <> vbYellow Then
                a(i, C + 1) = Rng(i, sCol)
                If Len(b(2, C + 1)) Then b(2, C + 1) = b(2, C + 1) & "," & a(i, C + 1) Else b(2, C + 1) = a(i, C + 1)
                Exit For
            End If
        Else
            Exit For
        End If
    Next j
  Next i
For i = 1 To sRow
    C = sCol - 1
    For j = sCol - 1 To 1 Step -1
        If Rng(i, sCol - 1).Interior.Pattern = xlNone Then
        If Rng(i, j).Interior.Pattern = xlNone Then C = C - 1
            If Rng(i, j).Interior.Pattern <> xlNone Then
                x(i, C + 1) = Rng(i, sCol)
                If Len(y(2, C + 1)) Then y(2, C + 1) = y(2, C + 1) & "," & x(i, C + 1) Else y(2, C + 1) = x(i, C + 1)
                Exit For
            End If
        Else
            Exit For
        End If
    Next j
Next i
With Sheet1
  .Range("A2").Offset(, sCol + 2).Resize(100000, sCol * 2).ClearContents
  .Range("A2").Offset(, sCol + 2).Resize(2, sCol - 1).Value = b
  .Range("A4").Offset(, sCol + 2).Resize(sRow, sCol - 1).Value = a
  .Range("A2").Offset(, sCol * 2 + 3).Resize(2, sCol - 1).Value = y
  .Range("A4").Offset(, sCol * 2 + 3).Resize(sRow, sCol - 1).Value = x
End With
Application.ScreenUpdating = True
MsgBox "OK"
End Sub
 
Lần chỉnh sửa cuối:
Cám ơn Anh.

Cám ơn Anh đã chiếu cố! Nhưng khi chạy code thì lỗi báo
ReDim S(1 To 100)
For i = 4 To Lr
t = t + 1 .
Em dốt vụ VBA nên không biết chỉnh sao ạ!
Đúng như Anh@ Hoàng Tuấn 868 chuẩn đoán, khai vừa thiếu biến vừa thừa biến.
Bạn thay lại code cũ bằng code này.
Mã:
Option Explicit

Sub XYZ2()
Dim i&, j&, t&, k&, Z&, M&, Comau&, Kmau&, Lr&, Col&
Dim eRng As Range, Sh As Worksheet
Dim Arr(), KQK(), KQM(), SoLan(), TieudeC(), TieudeK()
Dim Dic As Object, Key
Dim Ketqua As Range

Application.ScreenUpdating = False

On Error Resume Next
Set Sh = Sheet1
Lr = Sh.Cells(Rows.Count, 1).End(xlUp).Row

ReDim KQM(1 To Lr - 3, 1 To 100)
ReDim KQK(1 To Lr - 3, 1 To 100)
ReDim TieudeC(1 To 1, 1 To 100)
ReDim TieudeK(1 To 1, 1 To 100)
For i = 4 To Lr
t = t + 1
Set eRng = Sh.Range(Cells(i, 1), Cells(i, Sh.Range("A" & i).End(xlToRight).Column))
Col = eRng.Columns.Count
    For j = Col To 1 Step -1
        If eRng(1, j) <> Empty Then
            If eRng(1, j).Interior.Color = vbYellow Then
                Comau = Comau + 1
            Else
               Kmau = Kmau + 1
                If Comau >= 1 Then Exit For
            End If
        End If
    Next j
        TieudeC(1, Comau) = "Liên tuc có màu liên tiêp " & Comau
        TieudeK(1, Kmau - 1) = "Liên tuc không có màu liên tiêp " & Kmau - 1
            KQM(t, Comau) = eRng(1, Col)
            KQK(t, Kmau - 1) = eRng(1, Col)
    If Comau > M Then M = Comau
       Comau = 0: Kmau = 0: Set Rng = Nothing
Next i

Sh.[J1].Resize(10000, 1000).ClearContents
Sh.[J1].Resize(1, M) = TieudeC
Sh.[J1].Resize(2, M).Interior.Color = vbYellow
Sh.[J1].Offset(0, M).Resize(1, M) = TieudeK
Sh.[J4].Resize(t, M) = KQM
Sh.[J4].Offset(0, M).Resize(t, M) = KQK

Arr = Sh.Range("J4", "J4").Resize(t, M * 2).Value
ReDim SoLan(1 To 1, 1 To UBound(Arr))

For i = 1 To UBound(Arr, 2)
Set Dic = CreateObject("Scripting.Dictionary")
    For j = 1 To UBound(Arr, 1)
        If Arr(j, i) <> Empty Then
            Key = Arr(j, i)
            If Not Dic.Exists(Key) Then
            k = k + 1: Dic.Add (Key), k
                If SoLan(1, i) = Empty Then SoLan(1, i) = Key Else SoLan(1, i) = SoLan(1, i) & "," & Key
            End If
        End If
    Next j
    Set Dic = Nothing
Next i
Sh.[J2].Resize(1, UBound(Arr)) = SoLan
Application.ScreenUpdating = True
MsgBox "OK!", vbInformation, "THÔNG BÁO"
End Sub
Nên tham khảo các code khác nữa nhé.
Bài đã được tự động gộp:

Chắc chắn kết quả chưa đúng ý thớt :D
Tôi thuộc tip người chậm hiểu nên không thể đoán đúng ý của chủ thớt, nhiều khi cứ code mò thôi. Ngay cả cái lỗi code bạn ấy đưa lên
" ...ReDim S(1 To 100)
For i = 4 To Lr
t = t + 1...."
Lỗi dòng nào? có bảng thông báo gì không? Cũng không nên cũng phải đoán đó là gì?
Tôi cũng nhắc bạn đó tham khảo các code khác. và vẫn nói bạn đó nếu sử dụng file tôi làm giúp bạn ấy vào mục đích chơi lô đề, đánh bạc... thì hãy chủ động liên hệ với đội ngũ làm tín dụng đen để được hỗ trợ, trợ giúp vô tư, vô bờ bến
 
Lần chỉnh sửa cuối:
File bài #63, rút bớt vòng for (Chưa kiểm lại kỹ không biết có lỗi gì không)
Mã:
Option Explicit

Sub Count_Color_NoColor()
Dim Rng As Range, I&, J&, R&, C&, Cols&, iColor&, NoColor&, colorArr$(), noColorArr$()
'--------------------------- Nhap lieu dau vao
Const MyColor = vbYellow
Const MyNoColor = xlNone
Const iR& = 3 'Dòng phía tren moi bang
Set Rng = Sheets("Sheet1").Range("A4:H26") 'Dong du lieu bat dau >=4
'----------------------------
R = Rng.Rows.Count: C = Rng.Columns.Count
Cols = C - 2 'Cot arr can offset
ReDim colorArr(1 To R + iR, 1 To Cols)
ReDim noColorArr(1 To R + iR, 1 To Cols)
For I = 1 To Cols
    colorArr(1, I) = "Lien tuc co mau lien tiep " & Cols + 1 - I
    noColorArr(1, I) = "Khong co mau lien tiep " & Cols + 1 - I
Next
For I = 1 To R
    iColor = 0: NoColor = 0
    For J = C - 1 To 2 Step -1
        If Rng(I, J).Interior.Color = MyColor Then
            If NoColor = 0 Then iColor = iColor + 1 Else Exit For
        ElseIf Rng(I, J).Interior.Pattern = MyNoColor Then
            If iColor = 0 Then NoColor = NoColor + 1 Else Exit For
        End If
    Next
    If iColor Then
        J = Cols + 1 - iColor
        colorArr(I + iR, J) = Rng(I, C).Text
        colorArr(2, J) = IIf(colorArr(2, J) = "", Rng(I, C).Text, colorArr(2, J) & "," & Rng(I, C).Text)
    Else
        J = Cols + 1 - NoColor
        noColorArr(I + iR, J) = Rng(I, C).Text
        noColorArr(2, J) = IIf(noColorArr(2, J) = "", Rng(I, C).Text, noColorArr(2, J) & "," & Rng(I, C).Text)
    End If
Next
Rng(1, C).Offset(-iR, 2).Resize(R + iR, Cols) = colorArr
Rng(1, C).Offset(-iR, Cols + 3).Resize(R + iR, Cols) = noColorArr
End Sub
 
File bài #63, rút bớt vòng for (Chưa kiểm lại kỹ không biết có lỗi gì không)
...
Trên tinh thần chia sẻ, học hỏi, bạn nên cho biết rút bớt vòng for thì được gì. Ví dụ, tiết kiệm được x lần con tính abc; tiết kiệm y lần chạy những dòng code def...
Tôi nói không phải do bắt bẻ. Chuyện tiết kiệm số lần tính là một trong những chỉ tiêu của refactor code.

Thỉnh thoảng có mấy người ở đây thách đố "giảm số vòng lặp" mà không thấy đưa mục đích gì.
 
Trên tinh thần chia sẻ, học hỏi, bạn nên cho biết rút bớt vòng for thì được gì. Ví dụ, tiết kiệm được x lần con tính abc; tiết kiệm y lần chạy những dòng code def...
Tôi nói không phải do bắt bẻ. Chuyện tiết kiệm số lần tính là một trong những chỉ tiêu của refactor code.

Thỉnh thoảng có mấy người ở đây thách đố "giảm số vòng lặp" mà không thấy đưa mục đích gì.
Thực ra em cũng không biết giải thích sao, em suy nghĩ kiểu như nếu đi chợ mà ra chợ xem hàng xong, nếu có món mình cần mua thì chạy về nhà lấy tiền ra để mua. Thay vào đó ta đem tiền đi từ đầu thì đỡ mệt. Vậy thôi bác :D, trong bài này em cũng chưa xem kỹ bài các bạn, chỉ là em nêu ra một cách làm khác giảm bớt vòng lặp đi thôi. Có vấn đề gì nhờ bác chỉ thêm!
 
Thực ra em cũng không biết giải thích sao, em suy nghĩ kiểu như nếu đi chợ mà ra chợ xem hàng xong, nếu có món mình cần mua thì chạy về nhà lấy tiền ra để mua. Thay vào đó ta đem tiền đi từ đầu thì đỡ mệt. Vậy thôi bác :D, trong bài này em cũng chưa xem kỹ bài các bạn, chỉ là em nêu ra một cách làm khác giảm bớt vòng lặp đi thôi. Có vấn đề gì nhờ bác chỉ thêm!
Tôi lười mở file bài #63 ra để xem code mà so sánh. Để dịp khác vậy.

Đại khái 1 cách so sánh:
For i = 1 To SoDong
For j = 1 To SoCot
a(i, j) = etCetera
Next j
Next i
Gom lại thành 1 vòng lặp:
For i = 1 To SoDong*SoCot
a((i-1)\SoCot+1, ((i-1) Mod SoCot)+1) = etCetera
Next i
Code ngắn hơn. Giảm được 1 vòng lặp, tức là giảm được SoDong lần đếm j từ 1 đến SoCot. Nói cách khác là giảm được SoDong*SoCot lần đếm trị j.
Ngược lại, mất SoDong*SoCot lần tính hai chỉ số mảng.
Số lần code gán etCetera như nhau. Số lần Goto (Next tức là Goto For) như nhau.
Như vậy, trước mắt là lỗ. Bởi con toán tính chỉ số phức tạp hơn con toán tăng 1 nhiều.

Vậy thì giảm từ 2 xuống 1 vòng lặp còn khác nhau những gì?
Câu trả lời sẽ hơi lạ đối với người mới viết code.
Khi ta có lệnh Exit For.
1 vòng lặp Exit là hết luôn.
2 vòng lặp Exit vòng trong vẫn còn vòng ngoài. Muốn hết luôn thì phải có code test và Exit lần nữa.
Như vậy, người ta có thể chọn loại Exit mà áp dụng 1 hay 2 vòng lặp.

Những điểm khác nhau còn lại thuộc về dạng cao cấp. Điển hình khi lệnh khởi vòng lặp có biểu thức gọi các hàm người dùng khác.
 
Dạ em gửi lại anh file. Nội dung mong muốn em viết ở trong file ak!
Bài đã được tự động gộp:
Chạy code . . .
Mã:
Sub XYZ()
  Dim sh As Worksheet, a$(), b$(), rng As Range
  Dim sRow&, Col&, i&, j&, c&, dC&, bYellow As Boolean
  Const sCol& = 20 'So cot ket qua
 
  Set sh = Sheets("Sheet1")
  Set rng = sh.Range("A4", sh.Range("X" & Rows.Count).End(xlUp))
  sRow = rng.Rows.Count: Col = rng.Columns.Count - 1
  ReDim a(1 To sRow, 1 To 2 * sCol + 2)
  ReDim b(1 To 1, 1 To 2 * sCol + 2)
  For i = 1 To sRow
    c = sCol + 1
    If rng(i, Col).Interior.Color = vbYellow Then
      bYellow = True
      dC = 0
    Else
      bYellow = False
      dC = sCol + 2
    End If
    For j = Col To 1 Step -1
      If (rng(i, j).Interior.Color = vbYellow) = bYellow Then
        c = c - 1
      Else
        If c >= 1 Then
          c = c + dC
          a(i, c) = rng(i, Col + 1)
          If InStr(1, b(1, c), a(i, c)) = 0 Then
            If Len(b(1, c)) Then b(1, c) = b(1, c) & "," & a(i, c) Else b(1, c) = a(i, c)
          End If
          Exit For
        End If
      End If
    Next j
  Next i
  sh.Range("Z2:BO10000").Clear
  sh.Range("Z4").Resize(sRow, 2 * sCol + 2) = a
  sh.Range("Z2").Resize(, 2 * sCol + 2) = b
End Sub
 
... thì hãy chủ động liên hệ với đội ngũ làm tín dụng đen để được hỗ trợ, trợ giúp vô tư, vô bờ bến
Vô bờ bến thì không có vấn đề gì. Nhưng dân không biết đọc code thì làm sao biết là code vô tư?
 
Vô bờ bến thì không có vấn đề gì. Nhưng dân không biết đọc code thì làm sao biết là code vô tư?
Tôi chỉ muốn nhắc bạn ấy là nếu sử dụng file tôi để tính toán lô đề, cờ bạc gửi thì hãy cảnh giác (có thể sẽ phải ra đê để ở...). Vì có thể sẽ không đem lại kết quả sau cùng như mong muốn.
Còn bạn ấy có hiểu hay không hiểu thì bạn ấy cứ đọc hết các bài thì cũng có thể hiểu được code vô tư hay không vô tư.
 
Đúng như Anh@ Hoàng Tuấn 868 chuẩn đoán, khai vừa thiếu biến vừa thừa biến.
Bạn thay lại code cũ bằng code này.
Mã:
Option Explicit

Sub XYZ2()
Dim i&, j&, t&, k&, Z&, M&, Comau&, Kmau&, Lr&, Col&
Dim eRng As Range, Sh As Worksheet
Dim Arr(), KQK(), KQM(), SoLan(), TieudeC(), TieudeK()
Dim Dic As Object, Key
Dim Ketqua As Range

Application.ScreenUpdating = False

On Error Resume Next
Set Sh = Sheet1
Lr = Sh.Cells(Rows.Count, 1).End(xlUp).Row

ReDim KQM(1 To Lr - 3, 1 To 100)
ReDim KQK(1 To Lr - 3, 1 To 100)
ReDim TieudeC(1 To 1, 1 To 100)
ReDim TieudeK(1 To 1, 1 To 100)
For i = 4 To Lr
t = t + 1
Set eRng = Sh.Range(Cells(i, 1), Cells(i, Sh.Range("A" & i).End(xlToRight).Column))
Col = eRng.Columns.Count
    For j = Col To 1 Step -1
        If eRng(1, j) <> Empty Then
            If eRng(1, j).Interior.Color = vbYellow Then
                Comau = Comau + 1
            Else
               Kmau = Kmau + 1
                If Comau >= 1 Then Exit For
            End If
        End If
    Next j
        TieudeC(1, Comau) = "Liên tuc có màu liên tiêp " & Comau
        TieudeK(1, Kmau - 1) = "Liên tuc không có màu liên tiêp " & Kmau - 1
            KQM(t, Comau) = eRng(1, Col)
            KQK(t, Kmau - 1) = eRng(1, Col)
    If Comau > M Then M = Comau
       Comau = 0: Kmau = 0: Set Rng = Nothing
Next i

Sh.[J1].Resize(10000, 1000).ClearContents
Sh.[J1].Resize(1, M) = TieudeC
Sh.[J1].Resize(2, M).Interior.Color = vbYellow
Sh.[J1].Offset(0, M).Resize(1, M) = TieudeK
Sh.[J4].Resize(t, M) = KQM
Sh.[J4].Offset(0, M).Resize(t, M) = KQK

Arr = Sh.Range("J4", "J4").Resize(t, M * 2).Value
ReDim SoLan(1 To 1, 1 To UBound(Arr))

For i = 1 To UBound(Arr, 2)
Set Dic = CreateObject("Scripting.Dictionary")
    For j = 1 To UBound(Arr, 1)
        If Arr(j, i) <> Empty Then
            Key = Arr(j, i)
            If Not Dic.Exists(Key) Then
            k = k + 1: Dic.Add (Key), k
                If SoLan(1, i) = Empty Then SoLan(1, i) = Key Else SoLan(1, i) = SoLan(1, i) & "," & Key
            End If
        End If
    Next j
    Set Dic = Nothing
Next i
Sh.[J2].Resize(1, UBound(Arr)) = SoLan
Application.ScreenUpdating = True
MsgBox "OK!", vbInformation, "THÔNG BÁO"
End Sub
Nên tham khảo các code khác nữa nhé.
Bài đã được tự động gộp:


Tôi thuộc tip người chậm hiểu nên không thể đoán đúng ý của chủ thớt, nhiều khi cứ code mò thôi. Ngay cả cái lỗi code bạn ấy đưa lên
" ...ReDim S(1 To 100)
For i = 4 To Lr
t = t + 1...."
Lỗi dòng nào? có bảng thông báo gì không? Cũng không nên cũng phải đoán đó là gì?
Tôi cũng nhắc bạn đó tham khảo các code khác. và vẫn nói bạn đó nếu sử dụng file tôi làm giúp bạn ấy vào mục đích chơi lô đề, đánh bạc... thì hãy chủ động liên hệ với đội ngũ làm tín dụng đen để được hỗ trợ, trợ giúp vô tư, vô bờ bến
Dạ mong anh bỏ quá cho, không biết nói gì ngoài Cảm ơn Anh. Chúc Anh luôn mạnh khoẻ và Thành đạt!!!
 
Tôi chỉ muốn nhắc bạn ấy là nếu sử dụng file tôi để tính toán lô đề, cờ bạc gửi thì hãy cảnh giác (có thể sẽ phải ra đê để ở...). Vì có thể sẽ không đem lại kết quả sau cùng như mong muốn.
Còn bạn ấy có hiểu hay không hiểu thì bạn ấy cứ đọc hết các bài thì cũng có thể hiểu được code vô tư hay không vô tư.
Dạ Anh.. Cám ơn Anh vì sự giúp đỡ vô tư. Quả thực là vậy vì bài này mà làm Anh mất quá nhiều thời gian vì nội dung em đưa ra khiến anh không hiểu. Lẽ ra em nên viết là đếm kí từ phải qua trái đối với các dòng có bôi màu cùng hàng khi gặp ô không cùng hàng thì dừng lại và trả kết quả số lần... và đối với ô không có màu thì ngược lại. Dạ đó là lỗi phía em, văn phạm lủng củng làm Anh toàn phải đoán nội dung để code. Một lần nữa chúc Anh và Các Anh/ Chị trên diễn đàn luôn mạnh khoẻ, hạnh phúc, thành công!!
Xin cám ơn tất cả mọi người đã quan tâm giúp đỡ!
Trân trọng/
Bài đã được tự động gộp:

Bạn có giận tôi thì giân, chứ tôi có lý do gì giân bạn đâu mà phải bỏ quá cho ?
thì cũng tại em diễn đạt không chuẩn, làm mất thời gian code đi code lại ý mà. Nếu không phiền Anh có thể cho em xin số điện thoại để tiện liên lạc ak!
 
Chạy 2 code . . .
Mã:
Option Explicit
Sub Dem()
  Dim arr(), S, res(), str$, tmp$, t$, a$, d$
  Dim sR&, i&, k&, j&, N&, fC&, c&
  Const deli$ = ",.;:-"
  With Sheet1
    arr = .Range("A2", .Range("A2").End(xlDown)).Value
  End With
  sR = UBound(arr)
  ReDim res(1 To sR, 1 To 3)
  For i = 1 To sR
    str = Replace(arr(i, 1), " ", "") & ","
    N = Len(str)
    fC = 1
    k = 0
    tmp = "|"
    a = Empty: d = Empty
    For j = 1 To N
      c = InStr(1, deli, Mid(str, j, 1))
      If c > 0 Then
        t = Mid(str, fC, j - fC)
        If InStr(1, tmp, "|" & t & "|") = 0 Then
          k = k + 1
          tmp = tmp & t & "|"
          a = a & d & t
          d = Mid(deli, c, 1)
        End If
        fC = j + 1
      End If
    Next j
    If a = Empty Then res(i, 1) = str Else res(i, 1) = a
    res(i, 2) = k
  Next i
  Sheet1.Range("B2").Resize(sR).NumberFormat = "@"
  Sheet1.Range("B2").Resize(sR, 2) = res
End Sub

Sub Them()
  Dim arr(), res(), sR&, sC&, i&, j&

  arr = Sheet1.Range("E2:N2").Resize(10).Value
  sR = UBound(arr, 1): sC = UBound(arr, 2)
  For j = 1 To sC
    For i = 2 To sR
      If arr(i - 1, j) = 9 Then arr(i, j) = 0 Else arr(i, j) = arr(i - 1, j) + 1
    Next i
  Next j
  Sheet1.Range("E2:N2").Resize(10).Value = arr
End Sub
Em xin chân thành cám ơn Thầy nhiều! Xin chúc Thầy luôn mạnh khoẻ và vui.
Trân trọng/
Bài đã được tự động gộp:

Đúng như Anh@ Hoàng Tuấn 868 chuẩn đoán, khai vừa thiếu biến vừa thừa biến.
Bạn thay lại code cũ bằng code này.
Mã:
Option Explicit

Sub XYZ2()
Dim i&, j&, t&, k&, Z&, M&, Comau&, Kmau&, Lr&, Col&
Dim eRng As Range, Sh As Worksheet
Dim Arr(), KQK(), KQM(), SoLan(), TieudeC(), TieudeK()
Dim Dic As Object, Key
Dim Ketqua As Range

Application.ScreenUpdating = False

On Error Resume Next
Set Sh = Sheet1
Lr = Sh.Cells(Rows.Count, 1).End(xlUp).Row

ReDim KQM(1 To Lr - 3, 1 To 100)
ReDim KQK(1 To Lr - 3, 1 To 100)
ReDim TieudeC(1 To 1, 1 To 100)
ReDim TieudeK(1 To 1, 1 To 100)
For i = 4 To Lr
t = t + 1
Set eRng = Sh.Range(Cells(i, 1), Cells(i, Sh.Range("A" & i).End(xlToRight).Column))
Col = eRng.Columns.Count
    For j = Col To 1 Step -1
        If eRng(1, j) <> Empty Then
            If eRng(1, j).Interior.Color = vbYellow Then
                Comau = Comau + 1
            Else
               Kmau = Kmau + 1
                If Comau >= 1 Then Exit For
            End If
        End If
    Next j
        TieudeC(1, Comau) = "Liên tuc có màu liên tiêp " & Comau
        TieudeK(1, Kmau - 1) = "Liên tuc không có màu liên tiêp " & Kmau - 1
            KQM(t, Comau) = eRng(1, Col)
            KQK(t, Kmau - 1) = eRng(1, Col)
    If Comau > M Then M = Comau
       Comau = 0: Kmau = 0: Set Rng = Nothing
Next i

Sh.[J1].Resize(10000, 1000).ClearContents
Sh.[J1].Resize(1, M) = TieudeC
Sh.[J1].Resize(2, M).Interior.Color = vbYellow
Sh.[J1].Offset(0, M).Resize(1, M) = TieudeK
Sh.[J4].Resize(t, M) = KQM
Sh.[J4].Offset(0, M).Resize(t, M) = KQK

Arr = Sh.Range("J4", "J4").Resize(t, M * 2).Value
ReDim SoLan(1 To 1, 1 To UBound(Arr))

For i = 1 To UBound(Arr, 2)
Set Dic = CreateObject("Scripting.Dictionary")
    For j = 1 To UBound(Arr, 1)
        If Arr(j, i) <> Empty Then
            Key = Arr(j, i)
            If Not Dic.Exists(Key) Then
            k = k + 1: Dic.Add (Key), k
                If SoLan(1, i) = Empty Then SoLan(1, i) = Key Else SoLan(1, i) = SoLan(1, i) & "," & Key
            End If
        End If
    Next j
    Set Dic = Nothing
Next i
Sh.[J2].Resize(1, UBound(Arr)) = SoLan
Application.ScreenUpdating = True
MsgBox "OK!", vbInformation, "THÔNG BÁO"
End Sub
Nên tham khảo các code khác nữa nhé.
Bài đã được tự động gộp:


Tôi thuộc tip người chậm hiểu nên không thể đoán đúng ý của chủ thớt, nhiều khi cứ code mò thôi. Ngay cả cái lỗi code bạn ấy đưa lên
" ...ReDim S(1 To 100)
For i = 4 To Lr
t = t + 1...."
Lỗi dòng nào? có bảng thông báo gì không? Cũng không nên cũng phải đoán đó là gì?
Tôi cũng nhắc bạn đó tham khảo các code khác. và vẫn nói bạn đó nếu sử dụng file tôi làm giúp bạn ấy vào mục đích chơi lô đề, đánh bạc... thì hãy chủ động liên hệ với đội ngũ làm tín dụng đen để được hỗ trợ, trợ giúp vô tư, vô bờ bến
Hihi Bác giận em rùi!. Em cám ơn Bác nhiều lắm. Chúc Bác luôn mạnh khoẻ và hạnh phúc.
Bài đã được tự động gộp:

File bài #63, rút bớt vòng for (Chưa kiểm lại kỹ không biết có lỗi gì không)
Mã:
Option Explicit

Sub Count_Color_NoColor()
Dim Rng As Range, I&, J&, R&, C&, Cols&, iColor&, NoColor&, colorArr$(), noColorArr$()
'--------------------------- Nhap lieu dau vao
Const MyColor = vbYellow
Const MyNoColor = xlNone
Const iR& = 3 'Dòng phía tren moi bang
Set Rng = Sheets("Sheet1").Range("A4:H26") 'Dong du lieu bat dau >=4
'----------------------------
R = Rng.Rows.Count: C = Rng.Columns.Count
Cols = C - 2 'Cot arr can offset
ReDim colorArr(1 To R + iR, 1 To Cols)
ReDim noColorArr(1 To R + iR, 1 To Cols)
For I = 1 To Cols
    colorArr(1, I) = "Lien tuc co mau lien tiep " & Cols + 1 - I
    noColorArr(1, I) = "Khong co mau lien tiep " & Cols + 1 - I
Next
For I = 1 To R
    iColor = 0: NoColor = 0
    For J = C - 1 To 2 Step -1
        If Rng(I, J).Interior.Color = MyColor Then
            If NoColor = 0 Then iColor = iColor + 1 Else Exit For
        ElseIf Rng(I, J).Interior.Pattern = MyNoColor Then
            If iColor = 0 Then NoColor = NoColor + 1 Else Exit For
        End If
    Next
    If iColor Then
        J = Cols + 1 - iColor
        colorArr(I + iR, J) = Rng(I, C).Text
        colorArr(2, J) = IIf(colorArr(2, J) = "", Rng(I, C).Text, colorArr(2, J) & "," & Rng(I, C).Text)
    Else
        J = Cols + 1 - NoColor
        noColorArr(I + iR, J) = Rng(I, C).Text
        noColorArr(2, J) = IIf(noColorArr(2, J) = "", Rng(I, C).Text, noColorArr(2, J) & "," & Rng(I, C).Text)
    End If
Next
Rng(1, C).Offset(-iR, 2).Resize(R + iR, Cols) = colorArr
Rng(1, C).Offset(-iR, Cols + 3).Resize(R + iR, Cols) = noColorArr
End Sub
Em cám ơn anh nhiều ạ. Chúc Anh luôn mạnh khoẻ
 
Dựa vào code của thầy @HieuCD. Mình có chỉnh sửa theo ý muốn của chủ topic. Ai đó có thể chỉ giúp cách tối ưu hoặc giản số lần duyệt với ạ
Mã:
Sub ABC()
Application.ScreenUpdating = False
Dim a$(), b$(), Rng As Range, sRow&, i&, j&, C&, sCol&, x$(), y$()
Set Rng = Sheet1.Range("A4").CurrentRegion
sRow = Rng.Rows.Count
  sCol = Rng.Columns.Count
  ReDim a(1 To sRow, 1 To sCol - 1)
  ReDim x(1 To sRow, 1 To sCol - 1)
  ReDim b(1 To 2, 1 To sCol - 1)
  ReDim y(1 To 2, 1 To sCol - 1)
  For j = sCol - 1 To 1 Step -1
    b(1, j) = "Lien tuc co mau lien tiep " & sCol - j
    y(1, j) = "Khong co mau lien tiep " & sCol - j
  Next
  For i = 1 To sRow
    C = sCol - 1
    For j = sCol - 1 To 1 Step -1
        If Rng(i, sCol - 1).Interior.Color = vbYellow Then
            If Rng(i, j).Interior.Color = vbYellow Then C = C - 1
            If Rng(i, j).Interior.Color <> vbYellow Then
                a(i, C + 1) = Rng(i, sCol)
                If Len(b(2, C + 1)) Then b(2, C + 1) = b(2, C + 1) & "," & a(i, C + 1) Else b(2, C + 1) = a(i, C + 1)
                Exit For
            End If
        Else
            Exit For
        End If
    Next j
  Next i
For i = 1 To sRow
    C = sCol - 1
    For j = sCol - 1 To 1 Step -1
        If Rng(i, sCol - 1).Interior.Pattern = xlNone Then
        If Rng(i, j).Interior.Pattern = xlNone Then C = C - 1
            If Rng(i, j).Interior.Pattern <> xlNone Then
                x(i, C + 1) = Rng(i, sCol)
                If Len(y(2, C + 1)) Then y(2, C + 1) = y(2, C + 1) & "," & x(i, C + 1) Else y(2, C + 1) = x(i, C + 1)
                Exit For
            End If
        Else
            Exit For
        End If
    Next j
Next i
With Sheet1
  .Range("A2").Offset(, sCol + 2).Resize(100000, sCol * 2).ClearContents
  .Range("A2").Offset(, sCol + 2).Resize(2, sCol - 1).Value = b
  .Range("A4").Offset(, sCol + 2).Resize(sRow, sCol - 1).Value = a
  .Range("A2").Offset(, sCol * 2 + 3).Resize(2, sCol - 1).Value = y
  .Range("A4").Offset(, sCol * 2 + 3).Resize(sRow, sCol - 1).Value = x
End With
Application.ScreenUpdating = True
MsgBox "OK"
End Sub
Cám ơn em... nếu nó chạy nhanh chút nữa thì đẹp
 

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

Back
Top Bottom