Nhờ giúp đỡ code lọc theo nhiều điều kiện. (2 người xem)

Liên hệ QC

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

pinklove

Thành viên thường trực
Tham gia
21/1/08
Bài viết
336
Được thích
42
Mình có file Điểm như đính kèm, Mình muốn lọc điểm lớn nhất của từng người ở sheet 1, lấy ra kết quả sang sheet 2. Nhờ các bạn giúp đỡ.
Nếu có thể thì giúp mình luôn code lọc điểm cao thứ 2 và thứ 3 ( Cái này có thể tùy chọn cần lấy kết quả thứ mấy)
 

File đính kèm

Mình có file Điểm như đính kèm, Mình muốn lọc điểm lớn nhất của từng người ở sheet 1, lấy ra kết quả sang sheet 2. Nhờ các bạn giúp đỡ.
Nếu có thể thì giúp mình luôn code lọc điểm cao thứ 2 và thứ 3 ( Cái này có thể tùy chọn cần lấy kết quả thứ mấy)
Bạn thử nhé.
Mã:
Sub khongxembongda()
    Dim arr, kq, i As Long, a As Long, lr As Long, dic As Object, dk As String, b As Long
    Set dic = CreateObject("scripting.dictionary")
    With Sheets("sheet1")
         lr = .Range("B" & Rows.Count).End(xlUp).Row
         arr = .Range("B2:E" & lr).Value
         ReDim kq(1 To UBound(arr), 1 To 5)
    End With
        For i = 1 To UBound(arr)
            dk = UCase(arr(i, 1))
            If Not dic.exists(dk) Then
               a = a + 1
               dic.Add dk, a
               kq(a, 1) = a
               kq(a, 2) = arr(i, 1)
               kq(a, 3) = arr(i, 2)
               kq(a, 4) = arr(i, 3)
               kq(a, 5) = arr(i, 4)
            Else
               b = dic.Item(dk)
               If kq(b, 4) < arr(i, 3) Then
                  kq(b, 3) = arr(i, 2)
                  kq(b, 4) = arr(i, 3)
                  kq(b, 5) = arr(i, 4)
               End If
           End If
      Next i
   With Sheets("sheet2")
        lr = .Range("B" & Rows.Count).End(xlUp).Row
        If lr > 2 Then .Range("A2:E" & lr).ClearContents
        If a Then .Range("A2:E2").Resize(a).Value = kq
  End With
End Sub
 
Upvote 0
Bạn thử nhé.
Mã:
Sub khongxembongda()
    Dim arr, kq, i As Long, a As Long, lr As Long, dic As Object, dk As String, b As Long
    Set dic = CreateObject("scripting.dictionary")
    With Sheets("sheet1")
         lr = .Range("B" & Rows.Count).End(xlUp).Row
         arr = .Range("B2:E" & lr).Value
         ReDim kq(1 To UBound(arr), 1 To 5)
    End With
        For i = 1 To UBound(arr)
            dk = UCase(arr(i, 1))
            If Not dic.exists(dk) Then
               a = a + 1
               dic.Add dk, a
               kq(a, 1) = a
               kq(a, 2) = arr(i, 1)
               kq(a, 3) = arr(i, 2)
               kq(a, 4) = arr(i, 3)
               kq(a, 5) = arr(i, 4)
            Else
               b = dic.Item(dk)
               If kq(b, 4) < arr(i, 3) Then
                  kq(b, 3) = arr(i, 2)
                  kq(b, 4) = arr(i, 3)
                  kq(b, 5) = arr(i, 4)
               End If
           End If
      Next i
   With Sheets("sheet2")
        lr = .Range("B" & Rows.Count).End(xlUp).Row
        If lr > 2 Then .Range("A2:E" & lr).ClearContents
        If a Then .Range("A2:E2").Resize(a).Value = kq
  End With
End Sub
Đúng rồi bạn ạ. Nhưng mình quên mất 1 cái, đó là như trong file mẫu thì nếu 1 người mà có nhiều kỳ thi có điểm cao nhất bằng nhau thì liệt kê tất cả luôn ạ.
Ngoài ra có thêm cái điểm cao thứ 2 và thứ 3 bạn giúp mình luôn nhé.
 
Upvote 0
Đúng rồi bạn ạ. Nhưng mình quên mất 1 cái, đó là như trong file mẫu thì nếu 1 người mà có nhiều kỳ thi có điểm cao nhất bằng nhau thì liệt kê tất cả luôn ạ.
Ngoài ra có thêm cái điểm cao thứ 2 và thứ 3 bạn giúp mình luôn nhé.
File điểm của bạn có thể sắp xếp theo thứ tự điểm từ trên xuống dưới được không.Hay bắt buộc phải để như vậy.
 
Upvote 0
File điểm của bạn có thể sắp xếp theo thứ tự điểm từ trên xuống dưới được không.Hay bắt buộc phải để như vậy.
Bắt buộc phải để vậy ạ
Bài đã được tự động gộp:

kq(a, 1) = a
kq(a, 2) = arr(i, 1)
kq(a, 3) = arr(i, 2)
kq(a, 4) = arr(i, 3)
kq(a, 5) = arr(i, 4)
Else
b = dic.Item(dk)
If kq(b, 4) < arr(i, 3) Then
kq(b, 3) = arr(i, 2)
kq(b, 4) = arr(i, 3)
kq(b, 5) = arr(i, 4)
End If
Cái đoạn này có thể viết gọn hơn lại được ko bạn nhỉ, vì lỡ dữ liệu có hàng chục cột chẳng hạn viết thế này sẽ dài ngoằng. Cái này mình muốn hiểu thêm nên hỏi thôi.
 
Lần chỉnh sửa cuối:
Upvote 0
Bắt buộc phải để vậy ạ
Bài đã được tự động gộp:


Cái đoạn này có thể viết gọn hơn lại được ko bạn nhỉ, vì lỡ dữ liệu có hàng chục cột chẳng hạn viết thế này sẽ dài ngoằng. Cái này mình muốn hiểu thêm nên hỏi thôi.
Dược Bạn thay thế bằng vòng lặp FOR Next.Nếu dữ liệu như vậy viết code dài lắm.Mà mình dạo này bận nên không viết được.Bạn đợi bạn khác giúp nhé.:D.
 
Upvote 0
Bạn làm theo thuật toán là sắp xếp theo thứ tự từ trên xuống dưới rồi duyệt dữ liệu từ trên xuống dưới.lấy các giá trị bằng nhau đầu tiên là được đáp án thứ nhất.lấy giá trị thứ 2 là được đáp án thứ 2.hihi
 
Upvote 0
Đúng rồi bạn ạ. Nhưng mình quên mất 1 cái, đó là như trong file mẫu thì nếu 1 người mà có nhiều kỳ thi có điểm cao nhất bằng nhau thì liệt kê tất cả luôn ạ.
Ngoài ra có thêm cái điểm cao thứ 2 và thứ 3 bạn giúp mình luôn nhé.
Điểm cao thứ 1 hoặc 2 hoặc 3... : Thay đổi giá trị của k
Mã:
Sub locdiem()
Dim DL
Dim Diem
Dim Mang
Dim Kq
Dim rws
Dim i, j, k, x, z, t
DL = Sheet1.Range("A1").CurrentRegion
rws = UBound(DL)
ReDim Diem(100)
With CreateObject("Scripting.Dictionary")
    For i = 2 To rws
        If .Exists(DL(i, 2)) = False Then
            Mang = Diem
            Mang(DL(i, 4)) = DL(i, 3)
            .Item(DL(i, 2)) = Mang
        Else
            Mang = .Item(DL(i, 2))
            Mang(DL(i, 4)) = Mang(DL(i, 4)) & IIf(Mang(DL(i, 4)), " ", "") & DL(i, 3)
            .Item(DL(i, 2)) = Mang
        End If
    Next i
    ReDim Kq(1 To rws, 1 To 5)
    k = 1
    x = 0
    For i = 0 To .Count - 1
        Mang = .Items()(i)
        z = 0
        For j = 100 To 0 Step -1
            If Mang(j) <> "" Then z = z + 1
            If z = k Then
                t = Mang(j)
                Exit For
            End If
        Next j
        If InStr(t, " ") = 0 Then
            x = x + 1
            Kq(x, 1) = x
            Kq(x, 2) = .Keys()(i)
            Kq(x, 3) = t
            Kq(x, 4) = j
        Else
            For Each z In Split(t)
                x = x + 1
                Kq(x, 1) = x
                Kq(x, 2) = .Keys()(i)
                Kq(x, 3) = z
                Kq(x, 4) = j
            Next z
        End If
    Next i
End With
Sheet2.Range("A2").Resize(x, UBound(Kq, 2)) = Kq
End Sub
 
Upvote 0
Điểm cao thứ 1 hoặc 2 hoặc 3... : Thay đổi giá trị của k
Mã:
Sub locdiem()
Dim DL
Dim Diem
Dim Mang
Dim Kq
Dim rws
Dim i, j, k, x, z, t
DL = Sheet1.Range("A1").CurrentRegion
rws = UBound(DL)
ReDim Diem(100)
With CreateObject("Scripting.Dictionary")
    For i = 2 To rws
        If .Exists(DL(i, 2)) = False Then
            Mang = Diem
            Mang(DL(i, 4)) = DL(i, 3)
            .Item(DL(i, 2)) = Mang
        Else
            Mang = .Item(DL(i, 2))
            Mang(DL(i, 4)) = Mang(DL(i, 4)) & IIf(Mang(DL(i, 4)), " ", "") & DL(i, 3)
            .Item(DL(i, 2)) = Mang
        End If
    Next i
    ReDim Kq(1 To rws, 1 To 5)
    k = 1
    x = 0
    For i = 0 To .Count - 1
        Mang = .Items()(i)
        z = 0
        For j = 100 To 0 Step -1
            If Mang(j) <> "" Then z = z + 1
            If z = k Then
                t = Mang(j)
                Exit For
            End If
        Next j
        If InStr(t, " ") = 0 Then
            x = x + 1
            Kq(x, 1) = x
            Kq(x, 2) = .Keys()(i)
            Kq(x, 3) = t
            Kq(x, 4) = j
        Else
            For Each z In Split(t)
                x = x + 1
                Kq(x, 1) = x
                Kq(x, 2) = .Keys()(i)
                Kq(x, 3) = z
                Kq(x, 4) = j
            Next z
        End If
    Next i
End With
Sheet2.Range("A2").Resize(x, UBound(Kq, 2)) = Kq
End Sub
Cảm ơn bạn, đúng như ý mình rồi đó ạ. Nhưng code của bạn "snow25" mình đọc có thể hiểu được, chứ code của bạn mình ngồi đến giờ này ngâm vẫn chưa hiểu hết. Bạn có thể chú thích code giúp mình không? Mình cũng đang học nên rất muốn hiểu được, sau đỡ hỏi.
Bài đã được tự động gộp:

Bạn làm theo thuật toán là sắp xếp theo thứ tự từ trên xuống dưới rồi duyệt dữ liệu từ trên xuống dưới.lấy các giá trị bằng nhau đầu tiên là được đáp án thứ nhất.lấy giá trị thứ 2 là được đáp án thứ 2.hihi
Với code của bạn thì để lấy giá trị bằng nhau thứ 2 mình phải sửa thế nào ạ??
 
Upvote 0
Cảm ơn bạn, đúng như ý mình rồi đó ạ. Nhưng code của bạn "snow25" mình đọc có thể hiểu được, chứ code của bạn mình ngồi đến giờ này ngâm vẫn chưa hiểu hết. Bạn có thể chú thích code giúp mình không? Mình cũng đang học nên rất muốn hiểu được, sau đỡ hỏi.
Bạn xem chú thích bên dưới
Mã:
Sub locdiem()
Dim DL
Dim Diem
Dim Mang
Dim Kq
Dim rws
Dim i, j, k, x, z, t
DL = Sheet1.Range("A1").CurrentRegion
rws = UBound(DL)
ReDim Diem(100)
With CreateObject("Scripting.Dictionary")
    'Nap danh sach vao Dic.
    'Key=Ten; Item=Mang 101 phan tu ( 0-100 )
    'Lay diem so lam vitri trong Mang, dien lan thi vao vi tri do
    For i = 2 To rws
        If .Exists(DL(i, 2)) = False Then
            Mang = Diem '<--Mang 101 phan tu ( 0-100 )
            Mang(DL(i, 4)) = DL(i, 3) '<--'Lay diem so lam vitri trong Mang, dien lan thi vao vitri do
            .Item(DL(i, 2)) = Mang
        Else
            Mang = .Item(DL(i, 2))
            Mang(DL(i, 4)) = Mang(DL(i, 4)) & IIf(Mang(DL(i, 4)), " ", "") & DL(i, 3)
            .Item(DL(i, 2)) = Mang
        End If
    Next i
    'KT Nap danh sach vao Dic.
    
    'Xuat ket qua
    ReDim Kq(1 To rws, 1 To 5)
    k = 1
    x = 0
    For i = 0 To .Count - 1
        Mang = .Items()(i) 'Keys()(i)=Ten; .Items()(i)=Danh sach lan thi tuong ung
        
        'Dem nguoc tu 100-0, tim diem thi cao thu k, lay ra so lan thi tai diem do
        z = 0
        For j = 100 To 0 Step -1
            If Mang(j) <> "" Then z = z + 1
            If z = k Then
                t = Mang(j)
                Exit For
            End If
        Next j
        'KT Dem nguoc tu 100-0, tim diem thi cao thu k, lay ra so lan thi tai diem do
        
        'Kiem tra xem thi 1 hay nhieu lan, dien diem so, lan thi vao Kq
        If InStr(t, " ") = 0 Then '<--Thi 1 lan
            x = x + 1
            Kq(x, 1) = x
            Kq(x, 2) = .Keys()(i)
            Kq(x, 3) = t
            Kq(x, 4) = j
        Else
            For Each z In Split(t) '<--Thi >1 lan
                x = x + 1
                Kq(x, 1) = x
                Kq(x, 2) = .Keys()(i)
                Kq(x, 3) = z
                Kq(x, 4) = j
            Next z
        End If
        'KT Kiem tra xem thi 1 hay nhieu lan, dien diem so, lan thi vao Kq
    Next i
    'KT Xuat ket qua
End With
Sheet2.Range("A2").Resize(x, UBound(Kq, 2)) = Kq
End Sub
 
Upvote 0
Mình có file Điểm như đính kèm, Mình muốn lọc điểm lớn nhất của từng người ở sheet 1, lấy ra kết quả sang sheet 2. Nhờ các bạn giúp đỡ.
Nếu có thể thì giúp mình luôn code lọc điểm cao thứ 2 và thứ 3 ( Cái này có thể tùy chọn cần lấy kết quả thứ mấy)
Thử code
Mã:
Sub LargeNumeFilter()
  Dim sArr(), Res(), Arr(), tmp, SV$, Diem&
  Dim sRow&, iRnk&, i&, j&, k&, q&
 
  Sheet2.Range("A2:D500").ClearContents
  iRnk = Application.InputBox(prompt:="Nhap Diem Cao thu:", Type:=1)
  If iRnk = 0 Then Exit Sub
  With Sheet1
    sArr = .Range("B2", .Range("D" & Rows.Count).End(xlUp)).Value
  End With
  sRow = UBound(sArr)
  ReDim Arr(0 To 100)
  ReDim Res(1 To sRow, 1 To 4)
  With CreateObject("Scripting.Dictionary")
    For i = 1 To sRow
      SV = sArr(i, 1): Diem = sArr(i, 3)
      If .Exists(SV) = False Then
        k = k + 1:              Res(k, 1) = k
        Res(k, 2) = SV:        .Add SV, Arr
      End If
      tmp = .Item(SV)
      tmp(Diem) = tmp(Diem) & ", " & sArr(i, 2)
      .Item(SV) = tmp
    Next i
    If k Then
      For i = 1 To k
        tmp = .Item(Res(i, 2))
        q = 0
        For Diem = 100 To 0 Step -1
          If tmp(Diem) <> Empty Then q = q + 1
          If q = iRnk Then
            Res(i, 3) = Mid(tmp(Diem), 3, 50)
            Res(i, 4) = Diem
            Exit For
          End If
        Next Diem
      Next i
      Sheet2.Range("A2").Resize(k, 4) = Res
    End If
  End With
End Sub
 
Upvote 0
Thử code
Mã:
Sub LargeNumeFilter()
  Dim sArr(), Res(), Arr(), tmp, SV$, Diem&
  Dim sRow&, iRnk&, i&, j&, k&, q&

  Sheet2.Range("A2:D500").ClearContents
  iRnk = Application.InputBox(prompt:="Nhap Diem Cao thu:", Type:=1)
  If iRnk = 0 Then Exit Sub
  With Sheet1
    sArr = .Range("B2", .Range("D" & Rows.Count).End(xlUp)).Value
  End With
  sRow = UBound(sArr)
  ReDim Arr(0 To 100)
  ReDim Res(1 To sRow, 1 To 4)
  With CreateObject("Scripting.Dictionary")
    For i = 1 To sRow
      SV = sArr(i, 1): Diem = sArr(i, 3)
      If .Exists(SV) = False Then
        k = k + 1:              Res(k, 1) = k
        Res(k, 2) = SV:        .Add SV, Arr
      End If
      tmp = .Item(SV)
      tmp(Diem) = tmp(Diem) & ", " & sArr(i, 2)
      .Item(SV) = tmp
    Next i
    If k Then
      For i = 1 To k
        tmp = .Item(Res(i, 2))
        q = 0
        For Diem = 100 To 0 Step -1
          If tmp(Diem) <> Empty Then q = q + 1
          If q = iRnk Then
            Res(i, 3) = Mid(tmp(Diem), 3, 50)
            Res(i, 4) = Diem
            Exit For
          End If
        Next Diem
      Next i
      Sheet2.Range("A2").Resize(k, 4) = Res
    End If
  End With
End Sub
Thầy xử lý Array ra tay rồi
 
Upvote 0
Thử code
Mã:
Sub LargeNumeFilter()
  Dim sArr(), Res(), Arr(), tmp, SV$, Diem&
  Dim sRow&, iRnk&, i&, j&, k&, q&

  Sheet2.Range("A2:D500").ClearContents
  iRnk = Application.InputBox(prompt:="Nhap Diem Cao thu:", Type:=1)
  If iRnk = 0 Then Exit Sub
  With Sheet1
    sArr = .Range("B2", .Range("D" & Rows.Count).End(xlUp)).Value
  End With
  sRow = UBound(sArr)
  ReDim Arr(0 To 100)
  ReDim Res(1 To sRow, 1 To 4)
  With CreateObject("Scripting.Dictionary")
    For i = 1 To sRow
      SV = sArr(i, 1): Diem = sArr(i, 3)
      If .Exists(SV) = False Then
        k = k + 1:              Res(k, 1) = k
        Res(k, 2) = SV:        .Add SV, Arr
      End If
      tmp = .Item(SV)
      tmp(Diem) = tmp(Diem) & ", " & sArr(i, 2)
      .Item(SV) = tmp
    Next i
    If k Then
      For i = 1 To k
        tmp = .Item(Res(i, 2))
        q = 0
        For Diem = 100 To 0 Step -1
          If tmp(Diem) <> Empty Then q = q + 1
          If q = iRnk Then
            Res(i, 3) = Mid(tmp(Diem), 3, 50)
            Res(i, 4) = Diem
            Exit For
          End If
        Next Diem
      Next i
      Sheet2.Range("A2").Resize(k, 4) = Res
    End If
  End With
End Sub
Cảm ơn bác ạ, code rất hay ạ. Bác cho em xin cái giải thích code được không ạ.
 
Upvote 0
Cảm ơn bác ạ, code rất hay ạ. Bác cho em xin cái giải thích code được không ạ.
Mã:
Sub LargeNumeFilter()
  Dim sArr(), Res(), Arr(), tmp, SV$, Diem&
  Dim sRow&, iRnk&, i&, j&, k&, q&
 
  Sheet2.Range("A2:D500").ClearContents 'Xoa ket qua
  iRnk = Application.InputBox(prompt:="Nhap Diem Cao thu:", Type:=1) 'Nhap tuy chon Diem Cao thu
  If iRnk = 0 Then Exit Sub 'Khong nhap tuy chon thoat sub
  With Sheet1
    sArr = .Range("B2", .Range("D" & Rows.count).End(xlUp)).Value 'Tao mang du lieu
  End With
  sRow = UBound(sArr) 'So dong du lieu
  ReDim Arr(0 To 100) 'Mang "Lan Thi" voi thu tu dong la "Diem" tu 0 den 100
  ReDim Res(1 To sRow, 1 To 4) 'Mang Ket Qua
  With CreateObject("Scripting.Dictionary")
    For i = 1 To sRow
      SV = sArr(i, 1) 'Ten Sinh Vien
      Diem = sArr(i, 3) 'Diem so cua sinh vien
      If .Exists(SV) = False Then 'Loc sinh vien duy nhat
        k = k + 1
        Res(k, 1) = k 'So thu tu sinh vien
        Res(k, 2) = SV 'Ten Sinh Vien
        .Add SV, Arr 'Add sinh vien vao Dic de loai trung, voi Item la mang Diem
      End If
      tmp = .Item(SV) 'Mang "Lan Thi"
      tmp(Diem) = tmp(Diem) & ", " & sArr(i, 2) 'Gan "Lan Thi" vào dong "Diem"
      .Item(SV) = tmp 'Gan tmp vào Item cua Dic
    Next i
    If k Then 'Neu co danh sach sinh vien
      For i = 1 To k
        tmp = .Item(Res(i, 2)) 'Mang "Lan Thi" cua sinh vien thu i
        q = 0 'Bien dem
        For Diem = 100 To 0 Step -1
          If tmp(Diem) <> Empty Then q = q + 1 ' Diem Cao thu q
          If q = iRnk Then 'Neu Diem Cao thu thoa dieu kien
            Res(i, 3) = Mid(tmp(Diem), 3, 50) 'Lan thi, loai bo dau ", " o dau ket qua
            Res(i, 4) = Diem ' Diem Cao thu iRnk
            Exit For 'Thoat vong lap: For Diem = 100 To 0 Step -1
          End If
        Next Diem
      Next i
      Sheet2.Range("A2").Resize(k, 4) = Res 'Gan ket qua
    End If
  End With
End Sub
 
Upvote 0
Mã:
Sub LargeNumeFilter()
  Dim sArr(), Res(), Arr(), tmp, SV$, Diem&
  Dim sRow&, iRnk&, i&, j&, k&, q&

  Sheet2.Range("A2:D500").ClearContents 'Xoa ket qua
  iRnk = Application.InputBox(prompt:="Nhap Diem Cao thu:", Type:=1) 'Nhap tuy chon Diem Cao thu
  If iRnk = 0 Then Exit Sub 'Khong nhap tuy chon thoat sub
  With Sheet1
    sArr = .Range("B2", .Range("D" & Rows.count).End(xlUp)).Value 'Tao mang du lieu
  End With
  sRow = UBound(sArr) 'So dong du lieu
  ReDim Arr(0 To 100) 'Mang "Lan Thi" voi thu tu dong la "Diem" tu 0 den 100
  ReDim Res(1 To sRow, 1 To 4) 'Mang Ket Qua
  With CreateObject("Scripting.Dictionary")
    For i = 1 To sRow
      SV = sArr(i, 1) 'Ten Sinh Vien
      Diem = sArr(i, 3) 'Diem so cua sinh vien
      If .Exists(SV) = False Then 'Loc sinh vien duy nhat
        k = k + 1
        Res(k, 1) = k 'So thu tu sinh vien
        Res(k, 2) = SV 'Ten Sinh Vien
        .Add SV, Arr 'Add sinh vien vao Dic de loai trung, voi Item la mang Diem
      End If
      tmp = .Item(SV) 'Mang "Lan Thi"
      tmp(Diem) = tmp(Diem) & ", " & sArr(i, 2) 'Gan "Lan Thi" vào dong "Diem"
      .Item(SV) = tmp 'Gan tmp vào Item cua Dic
    Next i
    If k Then 'Neu co danh sach sinh vien
      For i = 1 To k
        tmp = .Item(Res(i, 2)) 'Mang "Lan Thi" cua sinh vien thu i
        q = 0 'Bien dem
        For Diem = 100 To 0 Step -1
          If tmp(Diem) <> Empty Then q = q + 1 ' Diem Cao thu q
          If q = iRnk Then 'Neu Diem Cao thu thoa dieu kien
            Res(i, 3) = Mid(tmp(Diem), 3, 50) 'Lan thi, loai bo dau ", " o dau ket qua
            Res(i, 4) = Diem ' Diem Cao thu iRnk
            Exit For 'Thoat vong lap: For Diem = 100 To 0 Step -1
          End If
        Next Diem
      Next i
      Sheet2.Range("A2").Resize(k, 4) = Res 'Gan ket qua
    End If
  End With
End Sub
Em cảm ơn ạ
 
Upvote 0
Mã:
Sub LargeNumeFilter()
  Dim sArr(), Res(), Arr(), tmp, SV$, Diem&
  Dim sRow&, iRnk&, i&, j&, k&, q&

  Sheet2.Range("A2:D500").ClearContents 'Xoa ket qua
  iRnk = Application.InputBox(prompt:="Nhap Diem Cao thu:", Type:=1) 'Nhap tuy chon Diem Cao thu
  If iRnk = 0 Then Exit Sub 'Khong nhap tuy chon thoat sub
  With Sheet1
    sArr = .Range("B2", .Range("D" & Rows.count).End(xlUp)).Value 'Tao mang du lieu
  End With
  sRow = UBound(sArr) 'So dong du lieu
  ReDim Arr(0 To 100) 'Mang "Lan Thi" voi thu tu dong la "Diem" tu 0 den 100
  ReDim Res(1 To sRow, 1 To 4) 'Mang Ket Qua
  With CreateObject("Scripting.Dictionary")
    For i = 1 To sRow
      SV = sArr(i, 1) 'Ten Sinh Vien
      Diem = sArr(i, 3) 'Diem so cua sinh vien
      If .Exists(SV) = False Then 'Loc sinh vien duy nhat
        k = k + 1
        Res(k, 1) = k 'So thu tu sinh vien
        Res(k, 2) = SV 'Ten Sinh Vien
        .Add SV, Arr 'Add sinh vien vao Dic de loai trung, voi Item la mang Diem
      End If
      tmp = .Item(SV) 'Mang "Lan Thi"
      tmp(Diem) = tmp(Diem) & ", " & sArr(i, 2) 'Gan "Lan Thi" vào dong "Diem"
      .Item(SV) = tmp 'Gan tmp vào Item cua Dic
    Next i
    If k Then 'Neu co danh sach sinh vien
      For i = 1 To k
        tmp = .Item(Res(i, 2)) 'Mang "Lan Thi" cua sinh vien thu i
        q = 0 'Bien dem
        For Diem = 100 To 0 Step -1
          If tmp(Diem) <> Empty Then q = q + 1 ' Diem Cao thu q
          If q = iRnk Then 'Neu Diem Cao thu thoa dieu kien
            Res(i, 3) = Mid(tmp(Diem), 3, 50) 'Lan thi, loai bo dau ", " o dau ket qua
            Res(i, 4) = Diem ' Diem Cao thu iRnk
            Exit For 'Thoat vong lap: For Diem = 100 To 0 Step -1
          End If
        Next Diem
      Next i
      Sheet2.Range("A2").Resize(k, 4) = Res 'Gan ket qua
    End If
  End With
End Sub
Hi bác, em ngồi mò mấy ngày mà vẫn ko hiểu hết được code của bác. Em thử sửa thành cấu trúc file data kiểu khác rồi sửa code để được theo mong muốn nhưng không được. Em up file mới lên đây, nhờ bác code lại giúp theo cái này để em so sánh sự thay đổi giữa 2 code em rút ra được điều mình cần ạ?
Dữ liệu này đang là 1 lớp, bác code giúp em nếu là hàng chục lớp với hàng ngàn học sinh ạ.
 

File đính kèm

Upvote 0
Dùng AdvancedFilter thì Trình Văn Vịnh lớn 1 hay lớn 2 đều 86.
 
Upvote 0
Thấy cấu truc lại khác với file ban đầu.
Đúng rồi ạ. Ý em là muốn sửa code từ file ban đầu theo file này để e học. Nhưng sửa mãi ko thành. Nên e muốn nhờ tác giả code sửa để e so sánh, khi đó e sẽ hiểu code dễ hơn ạ. Đây đơn thuần chỉ là e muốn học thêm, còn nhu cầu của e thì file ban đầu là ok rồi.
 
Upvote 0
Hi bác, em ngồi mò mấy ngày mà vẫn ko hiểu hết được code của bác. Em thử sửa thành cấu trúc file data kiểu khác rồi sửa code để được theo mong muốn nhưng không được. Em up file mới lên đây, nhờ bác code lại giúp theo cái này để em so sánh sự thay đổi giữa 2 code em rút ra được điều mình cần ạ?
Dữ liệu này đang là 1 lớp, bác code giúp em nếu là hàng chục lớp với hàng ngàn học sinh ạ.
Làm sao phân biệt được SV khác nhau nhưng trùng tên?
 
Upvote 0
Dữ liệu chỉ 1 môn hay nhiều môn? Nếu nhiều môn thì sao?
Hiện tại em chỉ làm cho từng môn ạ. Từ cái code theo form mới này a giúp em, em sẽ cố gắng hiểu và mò để làm cho nhiều môn, nếu ko thể được em sẽ hỏi tiếp, như thế em sẽ học và nhớ đc lâu hơn ạ.
 
Upvote 0
Có thể bỏ cái vụ trùng đi cũng đc ạ, nếu cao nhất thì chỉ lấy 1 thôi ạ.
Hiện tại em chỉ làm cho từng môn ạ. Từ cái code theo form mới này a giúp em, em sẽ cố gắng hiểu và mò để làm cho nhiều môn, nếu ko thể được em sẽ hỏi tiếp, như thế em sẽ học và nhớ đc lâu hơn ạ.
Xem code
Mã:
Sub LargeNumeFilter()
  Dim sArr(), Res(), Arr(), tmp
  Dim sRow&, iRnk&, i&, k&, ik&, q&
  Dim fDay As Date, eDay As Date, maSV$, Diem&
  On Error Resume Next
  With Sheet2
    fDay = .Range("D1").Value 'Ngay dau
    eDay = .Range("D2").Value 'Ngay cuoi
    .Range("A5:E500").ClearContents                              'Xoa ket qua
  End With
  If Err.Number > 0 Or fDay > eDay Then 'Kiem tra tinh hop le ngay xuat bao cao
    MsgBox ("Xem lai dieu kien ngay thi Tu ... Den ...")
    Err.Clear
    Exit Sub
  End If
  iRnk = Application.InputBox(prompt:="Nhap Diem Cao thu:", Type:=1) 'Nhap tuy chon Diem Cao thu
  If iRnk = 0 Then Exit Sub                                          'Khong nhap tuy chon thoat sub
  With Sheet1
    sArr = .Range("E2", .Range("N" & Rows.Count).End(xlUp)).Value    'Tao mang du lieu
  End With
  sRow = UBound(sArr)                                                'So dong du lieu
  ReDim Arr(0 To 100)                                                'Mang "Lan Thi" voi thu tu dong la "Diem" tu 0 den 100
  ReDim Res(1 To sRow, 1 To 5)                                       'Mang Ket Qua
  With CreateObject("Scripting.Dictionary")
    For i = 1 To sRow
      If fDay <= sArr(i, 6) And eDay >= sArr(i, 6) Then
        maSV = sArr(i, 1)                                                'Ten Sinh Vien
        Diem = sArr(i, 10)                                              'Diem so cua sinh vien
        If .Exists(maSV) = False Then                                    'Loc sinh vien duy nhat
          k = k + 1
          Res(k, 1) = k                                                'So thu tu sinh vien
          Res(k, 2) = maSV  'Tính lai Ten Sinh Vien trong file thuc te
          .Add maSV, Arr                                                 'Add sinh vien vao Dic de loai trung, voi Item la mang Diem
        End If
        tmp = .Item(maSV)                                                'Mang "Thu tu dong cua sArr"
      'Gan thu tu dong i vào dong "Diem". Chon 1 trong 2 lenh duoi
        tmp(Diem) = i 'Lay lan thi cuoi
        'If tmp(Diem) = Empty Then tmp(Diem) = i  'Lay lan thi dau
        .Item(maSV) = tmp                                                'Gan tmp vào Item cua Dic
      End If
    Next i
    If k Then                                                        'Neu co danh sach sinh vien
      For i = 1 To k
        tmp = .Item(Res(i, 2))                                       'Mang "Lan Thi" cua sinh vien thu i
        q = 0                                                        'Bien dem
        For Diem = 100 To 0 Step -1
          If tmp(Diem) <> Empty Then q = q + 1                       ' Diem Cao thu q
          If q = iRnk Then                                           'Neu Diem Cao thu thoa dieu kien
            ik = tmp(Diem) ' thu tu dong cua sArr
            Res(i, 3) = sArr(ik, 6) 'Ngay thi
            Res(i, 4) = sArr(ik, 7) 'Gio thi
            Res(i, 5) = Diem                                         ' Diem Cao thu iRnk
            Exit For                                                 'Thoat vong lap: For Diem = 100 To 0 Step -1
          End If
        Next Diem
      Next i
      Sheet2.Range("A5").Resize(k, 5) = Res                          'Gan ket qua
    End If
  End With
End Sub
 

File đính kèm

Upvote 0
Xem code
Mã:
Sub LargeNumeFilter()
  Dim sArr(), Res(), Arr(), tmp
  Dim sRow&, iRnk&, i&, k&, ik&, q&
  Dim fDay As Date, eDay As Date, maSV$, Diem&
  On Error Resume Next
  With Sheet2
    fDay = .Range("D1").Value 'Ngay dau
    eDay = .Range("D2").Value 'Ngay cuoi
    .Range("A5:E500").ClearContents                              'Xoa ket qua
  End With
  If Err.Number > 0 Or fDay > eDay Then 'Kiem tra tinh hop le ngay xuat bao cao
    MsgBox ("Xem lai dieu kien ngay thi Tu ... Den ...")
    Err.Clear
    Exit Sub
  End If
  iRnk = Application.InputBox(prompt:="Nhap Diem Cao thu:", Type:=1) 'Nhap tuy chon Diem Cao thu
  If iRnk = 0 Then Exit Sub                                          'Khong nhap tuy chon thoat sub
  With Sheet1
    sArr = .Range("E2", .Range("N" & Rows.Count).End(xlUp)).Value    'Tao mang du lieu
  End With
  sRow = UBound(sArr)                                                'So dong du lieu
  ReDim Arr(0 To 100)                                                'Mang "Lan Thi" voi thu tu dong la "Diem" tu 0 den 100
  ReDim Res(1 To sRow, 1 To 5)                                       'Mang Ket Qua
  With CreateObject("Scripting.Dictionary")
    For i = 1 To sRow
      If fDay <= sArr(i, 6) And eDay >= sArr(i, 6) Then
        maSV = sArr(i, 1)                                                'Ten Sinh Vien
        Diem = sArr(i, 10)                                              'Diem so cua sinh vien
        If .Exists(maSV) = False Then                                    'Loc sinh vien duy nhat
          k = k + 1
          Res(k, 1) = k                                                'So thu tu sinh vien
          Res(k, 2) = maSV  'Tính lai Ten Sinh Vien trong file thuc te
          .Add maSV, Arr                                                 'Add sinh vien vao Dic de loai trung, voi Item la mang Diem
        End If
        tmp = .Item(maSV)                                                'Mang "Thu tu dong cua sArr"
      'Gan thu tu dong i vào dong "Diem". Chon 1 trong 2 lenh duoi
        tmp(Diem) = i 'Lay lan thi cuoi
        'If tmp(Diem) = Empty Then tmp(Diem) = i  'Lay lan thi dau
        .Item(maSV) = tmp                                                'Gan tmp vào Item cua Dic
      End If
    Next i
    If k Then                                                        'Neu co danh sach sinh vien
      For i = 1 To k
        tmp = .Item(Res(i, 2))                                       'Mang "Lan Thi" cua sinh vien thu i
        q = 0                                                        'Bien dem
        For Diem = 100 To 0 Step -1
          If tmp(Diem) <> Empty Then q = q + 1                       ' Diem Cao thu q
          If q = iRnk Then                                           'Neu Diem Cao thu thoa dieu kien
            ik = tmp(Diem) ' thu tu dong cua sArr
            Res(i, 3) = sArr(ik, 6) 'Ngay thi
            Res(i, 4) = sArr(ik, 7) 'Gio thi
            Res(i, 5) = Diem                                         ' Diem Cao thu iRnk
            Exit For                                                 'Thoat vong lap: For Diem = 100 To 0 Step -1
          End If
        Next Diem
      Next i
      Sheet2.Range("A5").Resize(k, 5) = Res                          'Gan ket qua
    End If
  End With
End Sub
Bài này nếu mình sắp xếp theo điểm rồi lấy vị trí có được không anh nhỉ.
 
Upvote 0
Xem code
Mã:
Sub LargeNumeFilter()
  Dim sArr(), Res(), Arr(), tmp
  Dim sRow&, iRnk&, i&, k&, ik&, q&
  Dim fDay As Date, eDay As Date, maSV$, Diem&
  On Error Resume Next
  With Sheet2
    fDay = .Range("D1").Value 'Ngay dau
    eDay = .Range("D2").Value 'Ngay cuoi
    .Range("A5:E500").ClearContents                              'Xoa ket qua
  End With
  If Err.Number > 0 Or fDay > eDay Then 'Kiem tra tinh hop le ngay xuat bao cao
    MsgBox ("Xem lai dieu kien ngay thi Tu ... Den ...")
    Err.Clear
    Exit Sub
  End If
  iRnk = Application.InputBox(prompt:="Nhap Diem Cao thu:", Type:=1) 'Nhap tuy chon Diem Cao thu
  If iRnk = 0 Then Exit Sub                                          'Khong nhap tuy chon thoat sub
  With Sheet1
    sArr = .Range("E2", .Range("N" & Rows.Count).End(xlUp)).Value    'Tao mang du lieu
  End With
  sRow = UBound(sArr)                                                'So dong du lieu
  ReDim Arr(0 To 100)                                                'Mang "Lan Thi" voi thu tu dong la "Diem" tu 0 den 100
  ReDim Res(1 To sRow, 1 To 5)                                       'Mang Ket Qua
  With CreateObject("Scripting.Dictionary")
    For i = 1 To sRow
      If fDay <= sArr(i, 6) And eDay >= sArr(i, 6) Then
        maSV = sArr(i, 1)                                                'Ten Sinh Vien
        Diem = sArr(i, 10)                                              'Diem so cua sinh vien
        If .Exists(maSV) = False Then                                    'Loc sinh vien duy nhat
          k = k + 1
          Res(k, 1) = k                                                'So thu tu sinh vien
          Res(k, 2) = maSV  'Tính lai Ten Sinh Vien trong file thuc te
          .Add maSV, Arr                                                 'Add sinh vien vao Dic de loai trung, voi Item la mang Diem
        End If
        tmp = .Item(maSV)                                                'Mang "Thu tu dong cua sArr"
      'Gan thu tu dong i vào dong "Diem". Chon 1 trong 2 lenh duoi
        tmp(Diem) = i 'Lay lan thi cuoi
        'If tmp(Diem) = Empty Then tmp(Diem) = i  'Lay lan thi dau
        .Item(maSV) = tmp                                                'Gan tmp vào Item cua Dic
      End If
    Next i
    If k Then                                                        'Neu co danh sach sinh vien
      For i = 1 To k
        tmp = .Item(Res(i, 2))                                       'Mang "Lan Thi" cua sinh vien thu i
        q = 0                                                        'Bien dem
        For Diem = 100 To 0 Step -1
          If tmp(Diem) <> Empty Then q = q + 1                       ' Diem Cao thu q
          If q = iRnk Then                                           'Neu Diem Cao thu thoa dieu kien
            ik = tmp(Diem) ' thu tu dong cua sArr
            Res(i, 3) = sArr(ik, 6) 'Ngay thi
            Res(i, 4) = sArr(ik, 7) 'Gio thi
            Res(i, 5) = Diem                                         ' Diem Cao thu iRnk
            Exit For                                                 'Thoat vong lap: For Diem = 100 To 0 Step -1
          End If
        Next Diem
      Next i
      Sheet2.Range("A5").Resize(k, 5) = Res                          'Gan ket qua
    End If
  End With
End Sub
Ở kết quả nếu em nhập điểm có phẩy nó đang tự động làm tròn, ví dụ e nhập 88,4 nó làm tròn thành 88, nhập 88,6 nó làm tròn thành 89, em muốn giữ nguyên như mình nhập vào thì làm sao ạ
 
Upvote 0
Ở kết quả nếu em nhập điểm có phẩy nó đang tự động làm tròn, ví dụ e nhập 88,4 nó làm tròn thành 88, nhập 88,6 nó làm tròn thành 89, em muốn giữ nguyên như mình nhập vào thì làm sao ạ
Bạn thử code này nhé.
Mã:
Sub laydiem()
    Const so As Integer = 1
    Dim arr, kq, a As Long, olit As Object, ngaydau As Long, ngaycuoi As Long, lr As Long, dk As String, diem As Double
    Dim i As Long, T, k As Integer, dic As Object, b As Long
    Set olit = CreateObject("System.Collections.SortedList")
    Set dic = CreateObject("scripting.dictionary")
    With Sheets("sheet2")
         ngaydau = .Range("D1").Value
         ngaycuoi = .Range("d2").Value
         .Range("A5:E500").ClearContents
    End With
   With Sheets("sheet1")
        lr = .Range("E" & Rows.Count).End(xlUp).Row
        If lr < 2 Then Exit Sub
        arr = .Range("E2:N" & lr).Value
        ReDim kq(1 To UBound(arr), 1 To 5)
        For i = 1 To UBound(arr)
            If ngaydau <= CLng(arr(i, 6)) And ngaycuoi >= CLng(arr(i, 6)) Then
               diem = arr(i, 10)
               If Not olit.contains(diem) Then
                  olit.Add diem, i
               Else
                  olit.Item(diem) = olit.Item(diem) & "#" & i
               End If
           End If
       Next i
       If olit.Count = 0 Then Exit Sub
       For k = olit.Count - 1 To 0 Step -1
           For Each T In Split(olit.getbyindex(k), "#")
               dk = arr(T, 1)
               If Not dic.exists(dk) Then
                  dic.Add dk, Array(1, arr(T, 10))
               End If
                  b = dic.Item(dk)(0)
                  diem = dic.Item(dk)(1)
                  If diem > arr(T, 10) Then
                     b = b + 1
                  End If
                  dic.Item(dk) = Array(b, arr(T, 10))
                  If b = so Then
                     a = a + 1
                     kq(a, 1) = a
                     kq(a, 2) = arr(T, 1)
                     kq(a, 3) = arr(T, 6)
                     kq(a, 4) = arr(T, 7)
                     kq(a, 5) = arr(T, 10)
                  End If
           Next T
       Next k
  End With
  With Sheets("sheet2")
       If a Then .Range("A5:E5").Resize(a).Value = kq
  End With
End Sub
 
Upvote 0
Bạn thử code này nhé.
Mã:
Sub laydiem()
    Const so As Integer = 1
    Dim arr, kq, a As Long, olit As Object, ngaydau As Long, ngaycuoi As Long, lr As Long, dk As String, diem As Double
    Dim i As Long, T, k As Integer, dic As Object, b As Long
    Set olit = CreateObject("System.Collections.SortedList")
    Set dic = CreateObject("scripting.dictionary")
    With Sheets("sheet2")
         ngaydau = .Range("D1").Value
         ngaycuoi = .Range("d2").Value
         .Range("A5:E500").ClearContents
    End With
   With Sheets("sheet1")
        lr = .Range("E" & Rows.Count).End(xlUp).Row
        If lr < 2 Then Exit Sub
        arr = .Range("E2:N" & lr).Value
        ReDim kq(1 To UBound(arr), 1 To 5)
        For i = 1 To UBound(arr)
            If ngaydau <= CLng(arr(i, 6)) And ngaycuoi >= CLng(arr(i, 6)) Then
               diem = arr(i, 10)
               If Not olit.contains(diem) Then
                  olit.Add diem, i
               Else
                  olit.Item(diem) = olit.Item(diem) & "#" & i
               End If
           End If
       Next i
       If olit.Count = 0 Then Exit Sub
       For k = olit.Count - 1 To 0 Step -1
           For Each T In Split(olit.getbyindex(k), "#")
               dk = arr(T, 1)
               If Not dic.exists(dk) Then
                  dic.Add dk, Array(1, arr(T, 10))
               End If
                  b = dic.Item(dk)(0)
                  diem = dic.Item(dk)(1)
                  If diem > arr(T, 10) Then
                     b = b + 1
                  End If
                  dic.Item(dk) = Array(b, arr(T, 10))
                  If b = so Then
                     a = a + 1
                     kq(a, 1) = a
                     kq(a, 2) = arr(T, 1)
                     kq(a, 3) = arr(T, 6)
                     kq(a, 4) = arr(T, 7)
                     kq(a, 5) = arr(T, 10)
                  End If
           Next T
       Next k
  End With
  With Sheets("sheet2")
       If a Then .Range("A5:E5").Resize(a).Value = kq
  End With
End Sub
1575962850620.png
Báo lỗi bạn ạ
 
Upvote 0
Bạn thử code này nhé.
Mã:
Sub laydiem()
    Const so As Integer = 1
    Dim arr, kq, a As Long, olit As Object, ngaydau As Long, ngaycuoi As Long, lr As Long, dk As String, diem As Double
    Dim i As Long, T, k As Integer, dic As Object, b As Long
    Set olit = CreateObject("System.Collections.SortedList")
    Set dic = CreateObject("scripting.dictionary")
    With Sheets("sheet2")
         ngaydau = .Range("D1").Value
         ngaycuoi = .Range("d2").Value
         .Range("A5:E500").ClearContents
    End With
   With Sheets("sheet1")
        lr = .Range("E" & Rows.Count).End(xlUp).Row
        If lr < 2 Then Exit Sub
        arr = .Range("E2:N" & lr).Value
        ReDim kq(1 To UBound(arr), 1 To 5)
        For i = 1 To UBound(arr)
            If ngaydau <= CLng(arr(i, 6)) And ngaycuoi >= CLng(arr(i, 6)) Then
               diem = arr(i, 10)
               If Not olit.contains(diem) Then
                  olit.Add diem, i
               Else
                  olit.Item(diem) = olit.Item(diem) & "#" & i
               End If
           End If
       Next i
       If olit.Count = 0 Then Exit Sub
       For k = olit.Count - 1 To 0 Step -1
           For Each T In Split(olit.getbyindex(k), "#")
               dk = arr(T, 1)
               If Not dic.exists(dk) Then
                  dic.Add dk, Array(1, arr(T, 10))
               End If
                  b = dic.Item(dk)(0)
                  diem = dic.Item(dk)(1)
                  If diem > arr(T, 10) Then
                     b = b + 1
                  End If
                  dic.Item(dk) = Array(b, arr(T, 10))
                  If b = so Then
                     a = a + 1
                     kq(a, 1) = a
                     kq(a, 2) = arr(T, 1)
                     kq(a, 3) = arr(T, 6)
                     kq(a, 4) = arr(T, 7)
                     kq(a, 5) = arr(T, 10)
                  End If
           Next T
       Next k
  End With
  With Sheets("sheet2")
       If a Then .Range("A5:E5").Resize(a).Value = kq
  End With
End Sub
Hay nhỉ :thumbs:
 
Upvote 0
Haha nhìn mấy code này nhớ lại thời sinh viên quá đi, giờ mình làm chuyên lập trình php mấy cái này không nhớ nhiều không giúp anh em được
 
Upvote 0
Ở kết quả nếu em nhập điểm có phẩy nó đang tự động làm tròn, ví dụ e nhập 88,4 nó làm tròn thành 88, nhập 88,6 nó làm tròn thành 89, em muốn giữ nguyên như mình nhập vào thì làm sao ạ
Chỉ chấp nhận 1 số lẽ
Chỉnh các dòng lệnh
ReDim Arr(0 To 1000)
Diem = sArr(i, 10) * 10
For Diem = 1000 To 0 Step -1
Res(i, 5) = Diem / 10
Mã:
Sub LargeNumeFilter()
  Dim sArr(), Res(), Arr(), tmp
  Dim sRow&, iRnk&, i&, k&, ik&, q&
  Dim fDay As Date, eDay As Date, maSV$, Diem&
  On Error Resume Next
  With Sheet2
    fDay = .Range("D1").Value 'Ngay dau
    eDay = .Range("D2").Value 'Ngay cuoi
    .Range("A5:E500").ClearContents                              'Xoa ket qua
  End With
  If Err.Number > 0 Or fDay > eDay Then 'Kiem tra tinh hop le ngay xuat bao cao
    MsgBox ("Xem lai dieu kien ngay thi Tu ... Den ...")
    Err.Clear
    Exit Sub
  End If
  iRnk = Application.InputBox(prompt:="Nhap Diem Cao thu:", Type:=1) 'Nhap tuy chon Diem Cao thu
  If iRnk = 0 Then Exit Sub                                          'Khong nhap tuy chon thoat sub
  With Sheet1
    sArr = .Range("E2", .Range("N" & Rows.Count).End(xlUp)).Value    'Tao mang du lieu
  End With
  sRow = UBound(sArr)                                                'So dong du lieu
  ReDim Arr(0 To 1000)                                                'Mang "Lan Thi" voi thu tu dong la "Diem" tu 0 den 100
  ReDim Res(1 To sRow, 1 To 5)                                       'Mang Ket Qua
  With CreateObject("Scripting.Dictionary")
    For i = 1 To sRow
      If fDay <= sArr(i, 6) And eDay >= sArr(i, 6) Then
        maSV = sArr(i, 1)                                                'Ten Sinh Vien
        Diem = sArr(i, 10) * 10                                            'Diem so cua sinh vien
        If .Exists(maSV) = False Then                                    'Loc sinh vien duy nhat
          k = k + 1
          Res(k, 1) = k                                                'So thu tu sinh vien
          Res(k, 2) = maSV  'Tính lai Ten Sinh Vien trong file thuc te
          .Add maSV, Arr                                                 'Add sinh vien vao Dic de loai trung, voi Item la mang Diem
        End If
        tmp = .Item(maSV)                                                'Mang "Thu tu dong cua sArr"
      'Gan thu tu dong i vào dong "Diem". Chon 1 trong 2 lenh duoi
        tmp(Diem) = i 'Lay lan thi cuoi
        'If tmp(Diem) = Empty Then tmp(Diem) = i  'Lay lan thi dau
        .Item(maSV) = tmp                                                'Gan tmp vào Item cua Dic
      End If
    Next i
    If k Then                                                        'Neu co danh sach sinh vien
      For i = 1 To k
        tmp = .Item(Res(i, 2))                                       'Mang "Lan Thi" cua sinh vien thu i
        q = 0                                                        'Bien dem
        For Diem = 1000 To 0 Step -1
          If tmp(Diem) <> Empty Then q = q + 1                       ' Diem Cao thu q
          If q = iRnk Then                                           'Neu Diem Cao thu thoa dieu kien
            ik = tmp(Diem) ' thu tu dong cua sArr
            Res(i, 3) = sArr(ik, 6) 'Ngay thi
            Res(i, 4) = sArr(ik, 7) 'Gio thi
            Res(i, 5) = Diem / 10                                       ' Diem Cao thu iRnk
            Exit For                                                 'Thoat vong lap: For Diem = 100 To 0 Step -1
          End If
        Next Diem
      Next i
      Sheet2.Range("A5").Resize(k, 5) = Res                          'Gan ket qua
    End If
  End With
End Sub
 
Upvote 0
Chỉ chấp nhận 1 số lẽ
Chỉnh các dòng lệnh
ReDim Arr(0 To 1000)
Diem = sArr(i, 10) * 10
For Diem = 1000 To 0 Step -1
Res(i, 5) = Diem / 10
Mã:
Sub LargeNumeFilter()
  Dim sArr(), Res(), Arr(), tmp
  Dim sRow&, iRnk&, i&, k&, ik&, q&
  Dim fDay As Date, eDay As Date, maSV$, Diem&
  On Error Resume Next
  With Sheet2
    fDay = .Range("D1").Value 'Ngay dau
    eDay = .Range("D2").Value 'Ngay cuoi
    .Range("A5:E500").ClearContents                              'Xoa ket qua
  End With
  If Err.Number > 0 Or fDay > eDay Then 'Kiem tra tinh hop le ngay xuat bao cao
    MsgBox ("Xem lai dieu kien ngay thi Tu ... Den ...")
    Err.Clear
    Exit Sub
  End If
  iRnk = Application.InputBox(prompt:="Nhap Diem Cao thu:", Type:=1) 'Nhap tuy chon Diem Cao thu
  If iRnk = 0 Then Exit Sub                                          'Khong nhap tuy chon thoat sub
  With Sheet1
    sArr = .Range("E2", .Range("N" & Rows.Count).End(xlUp)).Value    'Tao mang du lieu
  End With
  sRow = UBound(sArr)                                                'So dong du lieu
  ReDim Arr(0 To 1000)                                                'Mang "Lan Thi" voi thu tu dong la "Diem" tu 0 den 100
  ReDim Res(1 To sRow, 1 To 5)                                       'Mang Ket Qua
  With CreateObject("Scripting.Dictionary")
    For i = 1 To sRow
      If fDay <= sArr(i, 6) And eDay >= sArr(i, 6) Then
        maSV = sArr(i, 1)                                                'Ten Sinh Vien
        Diem = sArr(i, 10) * 10                                            'Diem so cua sinh vien
        If .Exists(maSV) = False Then                                    'Loc sinh vien duy nhat
          k = k + 1
          Res(k, 1) = k                                                'So thu tu sinh vien
          Res(k, 2) = maSV  'Tính lai Ten Sinh Vien trong file thuc te
          .Add maSV, Arr                                                 'Add sinh vien vao Dic de loai trung, voi Item la mang Diem
        End If
        tmp = .Item(maSV)                                                'Mang "Thu tu dong cua sArr"
      'Gan thu tu dong i vào dong "Diem". Chon 1 trong 2 lenh duoi
        tmp(Diem) = i 'Lay lan thi cuoi
        'If tmp(Diem) = Empty Then tmp(Diem) = i  'Lay lan thi dau
        .Item(maSV) = tmp                                                'Gan tmp vào Item cua Dic
      End If
    Next i
    If k Then                                                        'Neu co danh sach sinh vien
      For i = 1 To k
        tmp = .Item(Res(i, 2))                                       'Mang "Lan Thi" cua sinh vien thu i
        q = 0                                                        'Bien dem
        For Diem = 1000 To 0 Step -1
          If tmp(Diem) <> Empty Then q = q + 1                       ' Diem Cao thu q
          If q = iRnk Then                                           'Neu Diem Cao thu thoa dieu kien
            ik = tmp(Diem) ' thu tu dong cua sArr
            Res(i, 3) = sArr(ik, 6) 'Ngay thi
            Res(i, 4) = sArr(ik, 7) 'Gio thi
            Res(i, 5) = Diem / 10                                       ' Diem Cao thu iRnk
            Exit For                                                 'Thoat vong lap: For Diem = 100 To 0 Step -1
          End If
        Next Diem
      Next i
      Sheet2.Range("A5").Resize(k, 5) = Res                          'Gan ket qua
    End If
  End With
End Sub
Với file là điểm này thì 1 số lẻ là ok ạ. Nhưng em theo cách hiểu của em thì với mỗi số lẻ phía sau thì e thêm 1 số 0. Em thử với file có 5 số lẻ thì thấy code chậm hơn nhiều.
 
Upvote 0
Với file là điểm này thì 1 số lẻ là ok ạ. Nhưng em theo cách hiểu của em thì với mỗi số lẻ phía sau thì e thêm 1 số 0. Em thử với file có 5 số lẻ thì thấy code chậm hơn nhiều.
Đúng thế mà.Nó chạy nhiều vòng lặp hơn thì chậm hơn là phải rồi.
 
Upvote 0
Với file là điểm này thì 1 số lẻ là ok ạ. Nhưng em theo cách hiểu của em thì với mỗi số lẻ phía sau thì e thêm 1 số 0. Em thử với file có 5 số lẻ thì thấy code chậm hơn nhiều.
Nếu số lẻ nhiều mảng điểm sẽ lớn chạy nhiều lần sẽ chậm, dùng SortList ổn hơn
 
Upvote 0
Tức là sắp xếp theo thứ tự rồi mới quét ấy ạ
Chạy code
Mã:
Sub LargeNumeFilter()
  Dim sArr(), Res(), Arr(), bK As Boolean
  Dim sRow&, iRnk&, i&, k&, q&
  Dim fDay As Date, eDay As Date, maSV$, Diem
  On Error Resume Next
  With Sheet2
    fDay = .Range("D1").Value 'Ngay dau
    eDay = .Range("D2").Value 'Ngay cuoi
    .Range("A5:E500").ClearContents                              'Xoa ket qua
  End With
  If Err.Number > 0 Or fDay > eDay Then 'Kiem tra tinh hop le ngay xuat bao cao
    MsgBox ("Xem lai dieu kien ngay thi Tu ... Den ...")
    Err.Clear
    Exit Sub
  End If
  iRnk = Application.InputBox(prompt:="Nhap Diem Cao thu:", Type:=1) 'Nhap tuy chon Diem Cao thu
  If iRnk = 0 Then Exit Sub                                          'Khong nhap tuy chon thoat sub
  With Sheet1
    i = .Range("E" & Rows.Count).End(xlUp).Row 'Dong cuoi sheet1
    Arr = .Range("E2:N" & i).Value  'Tao mang du lieu Goc
    .Range("E2:N" & i).Sort .Range("E2"), 1, .Range("N2"), , 2, Header:=xlNo 'Sort du lieu
    sArr = .Range("E2:N" & i + 1).Value  'Tao mang du lieu da Sort
    .Range("E2:N" & i).Value = Arr 'Tra ve du lieu goc
  End With
  sRow = UBound(sArr)                                                'So dong du lieu
  ReDim Res(1 To sRow, 1 To 5)                                       'Mang Ket Qua
  For i = 1 To sRow - 1
    If fDay <= sArr(i, 6) And eDay >= sArr(i, 6) Then
      If maSV <> sArr(i, 1) Then                                                'Ten Sinh Vien
        maSV = sArr(i, 1)
        k = k + 1
        Res(k, 1) = k                                                'So thu tu sinh vien
        Res(k, 2) = maSV  'Tính lai Ten Sinh Vien trong file thuc te
        Diem = sArr(i, 10) + 1                                           'Diem so cua sinh vien
        q = 0
        bK = True
      End If
      If bK = True Then
        If Diem > sArr(i, 10) Then
          Diem = sArr(i, 10)
          q = q + 1
          If q = iRnk Then                                           'Neu Diem Cao thu thoa dieu kien
            Res(k, 3) = sArr(i, 6) 'Ngay thi
            Res(k, 4) = sArr(i, 7) 'Gio thi
            Res(k, 5) = Diem                                        ' Diem Cao thu iRnk
            bK = False                                               'Thoat vong lap: For Diem = 100 To 0 Step -1
          End If
        End If                                               'Gan tmp vào Item cua Dic
      End If
    End If
  Next i
  If k Then                                                        'Neu co danh sach sinh vien
    Sheet2.Range("A5").Resize(k, 5) = Res                          'Gan ket qua
  End If

End Sub
 
Upvote 0
Nếu số lẻ nhiều mảng điểm sẽ lớn chạy nhiều lần sẽ chậm, dùng SortList ổn hơn
Vậy với code này có cách nào tối ưu hơn ko ạ?
Bạn thử.
Mã:
Sub laydiem()
    Const so As Integer = 5
    Dim arr, kq, a As Long, olit As Object, ngaydau As Long, ngaycuoi As Long, lr As Long, dk As String, diem As Double
    Dim i As Long, T, k As Integer, dic As Object, b As Long, s1 As String, s2 As String, mang1, mang2, j As Long, m As Long
    Set dic = CreateObject("scripting.dictionary")
    With Sheets("sheet2")
         ngaydau = .Range("D1").Value
         ngaycuoi = .Range("d2").Value
         .Range("A5:E500").ClearContents
    End With
    With Sheets("sheet1")
        lr = .Range("E" & Rows.Count).End(xlUp).Row
        If lr < 2 Then Exit Sub
        arr = .Range("E2:N" & lr).Value
        ReDim kq(1 To UBound(arr), 1 To 5)
        For i = 1 To UBound(arr)
            If ngaydau <= CLng(arr(i, 6)) And ngaycuoi >= CLng(arr(i, 6)) Then
               dk = arr(i, 1)
               If Not dic.exists(dk) Then
                  dic.Add dk, Array("#" & arr(i, 10), "#" & i)
               Else
                  s1 = dic.Item(dk)(0) & "#" & arr(i, 10)
                  s2 = dic.Item(dk)(1) & "#" & i
                  dic.Item(dk) = Array(s1, s2)
               End If
           End If
       Next i
       For Each T In dic.keys
           b = 1
           s1 = dic.Item(T)(0)
           s2 = dic.Item(T)(1)
           mang1 = Split(s1, "#")
           mang2 = Split(s2, "#")
           k = UBound(mang1)
           For i = 1 To k
               For j = k - 1 To i Step -1
                   If mang1(j) < mang1(j + 1) Then
                      diem = mang1(j + 1)
                      mang1(j + 1) = mang1(j)
                      mang1(j) = diem
                   End If
               Next j
               If i > 1 Then
                  If mang1(i) < mang1(i - 1) Then b = b + 1
               End If
               If b = so Then
                  diem = mang1(i)
                  mang1 = Split(s1, "#")
                  For m = 1 To k
                      If mang1(m) = diem Then
                         a = a + 1
                         kq(a, 1) = a
                         kq(a, 2) = arr(mang2(m), 1)
                         kq(a, 3) = arr(mang2(m), 6)
                         kq(a, 4) = arr(mang2(m), 7)
                         kq(a, 5) = arr(mang2(m), 10)
                      End If
                 Next m
                 Exit For
             End If
           Next i
       Next
  End With
  With Sheets("sheet2")
       If a Then .Range("A5:E5").Resize(a).Value = kq
  End With
End Sub
 
Upvote 0
Chạy code
Mã:
Sub LargeNumeFilter()
  Dim sArr(), Res(), Arr(), bK As Boolean
  Dim sRow&, iRnk&, i&, k&, q&
  Dim fDay As Date, eDay As Date, maSV$, Diem
  On Error Resume Next
  With Sheet2
    fDay = .Range("D1").Value 'Ngay dau
    eDay = .Range("D2").Value 'Ngay cuoi
    .Range("A5:E500").ClearContents                              'Xoa ket qua
  End With
  If Err.Number > 0 Or fDay > eDay Then 'Kiem tra tinh hop le ngay xuat bao cao
    MsgBox ("Xem lai dieu kien ngay thi Tu ... Den ...")
    Err.Clear
    Exit Sub
  End If
  iRnk = Application.InputBox(prompt:="Nhap Diem Cao thu:", Type:=1) 'Nhap tuy chon Diem Cao thu
  If iRnk = 0 Then Exit Sub                                          'Khong nhap tuy chon thoat sub
  With Sheet1
    i = .Range("E" & Rows.Count).End(xlUp).Row 'Dong cuoi sheet1
    Arr = .Range("E2:N" & i).Value  'Tao mang du lieu Goc
    .Range("E2:N" & i).Sort .Range("E2"), 1, .Range("N2"), , 2, Header:=xlNo 'Sort du lieu
    sArr = .Range("E2:N" & i + 1).Value  'Tao mang du lieu da Sort
    .Range("E2:N" & i).Value = Arr 'Tra ve du lieu goc
  End With
  sRow = UBound(sArr)                                                'So dong du lieu
  ReDim Res(1 To sRow, 1 To 5)                                       'Mang Ket Qua
  For i = 1 To sRow - 1
    If fDay <= sArr(i, 6) And eDay >= sArr(i, 6) Then
      If maSV <> sArr(i, 1) Then                                                'Ten Sinh Vien
        maSV = sArr(i, 1)
        k = k + 1
        Res(k, 1) = k                                                'So thu tu sinh vien
        Res(k, 2) = maSV  'Tính lai Ten Sinh Vien trong file thuc te
        Diem = sArr(i, 10) + 1                                           'Diem so cua sinh vien
        q = 0
        bK = True
      End If
      If bK = True Then
        If Diem > sArr(i, 10) Then
          Diem = sArr(i, 10)
          q = q + 1
          If q = iRnk Then                                           'Neu Diem Cao thu thoa dieu kien
            Res(k, 3) = sArr(i, 6) 'Ngay thi
            Res(k, 4) = sArr(i, 7) 'Gio thi
            Res(k, 5) = Diem                                        ' Diem Cao thu iRnk
            bK = False                                               'Thoat vong lap: For Diem = 100 To 0 Step -1
          End If
        End If                                               'Gan tmp vào Item cua Dic
      End If
    End If
  Next i
  If k Then                                                        'Neu co danh sach sinh vien
    Sheet2.Range("A5").Resize(k, 5) = Res                          'Gan ket qua
  End If

End Sub
Chuẩn rồi ạ, qua những code anh đã giúp em ngẫm ra được rất nhiều điều, cảm ơn anh ạ.
Bạn thử.
Mã:
Sub laydiem()
    Const so As Integer = 5
    Dim arr, kq, a As Long, olit As Object, ngaydau As Long, ngaycuoi As Long, lr As Long, dk As String, diem As Double
    Dim i As Long, T, k As Integer, dic As Object, b As Long, s1 As String, s2 As String, mang1, mang2, j As Long, m As Long
    Set dic = CreateObject("scripting.dictionary")
    With Sheets("sheet2")
         ngaydau = .Range("D1").Value
         ngaycuoi = .Range("d2").Value
         .Range("A5:E500").ClearContents
    End With
    With Sheets("sheet1")
        lr = .Range("E" & Rows.Count).End(xlUp).Row
        If lr < 2 Then Exit Sub
        arr = .Range("E2:N" & lr).Value
        ReDim kq(1 To UBound(arr), 1 To 5)
        For i = 1 To UBound(arr)
            If ngaydau <= CLng(arr(i, 6)) And ngaycuoi >= CLng(arr(i, 6)) Then
               dk = arr(i, 1)
               If Not dic.exists(dk) Then
                  dic.Add dk, Array("#" & arr(i, 10), "#" & i)
               Else
                  s1 = dic.Item(dk)(0) & "#" & arr(i, 10)
                  s2 = dic.Item(dk)(1) & "#" & i
                  dic.Item(dk) = Array(s1, s2)
               End If
           End If
       Next i
       For Each T In dic.keys
           b = 1
           s1 = dic.Item(T)(0)
           s2 = dic.Item(T)(1)
           mang1 = Split(s1, "#")
           mang2 = Split(s2, "#")
           k = UBound(mang1)
           For i = 1 To k
               For j = k - 1 To i Step -1
                   If mang1(j) < mang1(j + 1) Then
                      diem = mang1(j + 1)
                      mang1(j + 1) = mang1(j)
                      mang1(j) = diem
                   End If
               Next j
               If i > 1 Then
                  If mang1(i) < mang1(i - 1) Then b = b + 1
               End If
               If b = so Then
                  diem = mang1(i)
                  mang1 = Split(s1, "#")
                  For m = 1 To k
                      If mang1(m) = diem Then
                         a = a + 1
                         kq(a, 1) = a
                         kq(a, 2) = arr(mang2(m), 1)
                         kq(a, 3) = arr(mang2(m), 6)
                         kq(a, 4) = arr(mang2(m), 7)
                         kq(a, 5) = arr(mang2(m), 10)
                      End If
                 Next m
                 Exit For
             End If
           Next i
       Next
  End With
  With Sheets("sheet2")
       If a Then .Range("A5:E5").Resize(a).Value = kq
  End With
End Sub
Mình chạy code này nó ko hoạt động, đứng im luôn bạn ạ
 
Upvote 0
Chuẩn rồi ạ, qua những code anh đã giúp em ngẫm ra được rất nhiều điều, cảm ơn anh ạ.

Mình chạy code này nó ko hoạt động, đứng im luôn bạn ạ
Bạn chỉnh chỗ này.
Const so As Integer = 5
Sửa thành số thứ tự bạn cần lấy.
 
Upvote 0

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

Back
Top Bottom