Option Explicit
Sub XYZ()
Dim sh As Worksheet
Dim arr(), aDiem, aTK(), a, b, c, d, res()
Dim soHS&, soNhom&, N&, i&, r&, j&, k&, gt&, le&
Dim soNu&, nMin&, nMax&, t&, hl&, iDC&, tmp$
Set sh = Sheets("8a2")
arr = sh.Range("D2", sh.Range("E" & Rows.Count).End(xlUp)).Value
soHS = UBound(arr)
On Error Resume Next
N = InputBox("Hay nhap so hoc sinh cua 1 nhom vào o bên duoi", "CHIA HOC SINH THEO NHOM")
If N = 0 Then
MsgBox " Ban phai nhap sô hoc sinh cua 1 nhóm": Exit Sub
End If
If N > soHS Then N = soHS
soNhom = Int(soHS / N) 'Phan HS thanh soNhom NHOM
On Error GoTo 0
Randomize
ReDim res(1 To soHS, 1 To 2)
ReDim aTK(1 To soNhom, 0 To 6)
ReDim a(1 To 8) 'Chia HS thanh 8 nhom theo Gioi Tinh va Diem
ReDim d(1 To 8) 'Hoc luc
aDiem = Array(0, 8, 7.5, 6.5, 5)
For i = 1 To soHS 'xep thu tu HS theo GT va Diem
If Len(arr(i, 1)) = 2 Then
gt = 0
soNu = soNu + 1
Else
gt = 1
End If
For j = 1 To 4
If arr(i, 2) >= aDiem(j) Then
a(j * 2 - gt) = a(j * 2 - gt) & "," & i
d(j * 2 - gt) = d(j * 2 - gt) & "," & j
Exit For
End If
Next j
Next i
a = Split(Join(a, ""), ",") 'Mang HS xep thu tu theo GT va Diem
d = Split(Join(d, ""), ",") 'Mang Loai Hoc luc
nMin = Int(soNu / soNhom) 'So nu it nhat trong 1 nhom
If nMin * soNhom = soNu Then nMax = nMin Else nMax = nMin + 1 'So nu nhieu nhat trong 1 nhom
le = soHS - soNhom * N
If le > 0 Then 'Chon ngau nhien HS le nhom
Call TaoMangNgauNhien(c, soHS)
Call TaoMangNgauNhien(b, soNhom)
For j = 1 To le
r = c(j)
res(a(r), 1) = b(j)
res(a(r), 2) = d(r)
If Len(arr(a(r), 1)) = 2 Then aTK(b(j), 2) = aTK(b(j), 2) + 1
a(r) = Empty
Next j
End If
Do 'Chon ngau nhien HS phan vào các nhóm
Call TaoMangNgauNhien(b, soNhom)
For j = 1 To soNhom
k = k + 1
If k > soHS Then Exit Do
If a(k) <> Empty Then
res(a(k), 1) = b(j)
res(a(k), 2) = d(k)
If Len(arr(a(k), 1)) = 2 Then aTK(b(j), 2) = aTK(b(j), 2) + 1
Else
j = j - 1
End If
Next j
Loop
DieuChinhTiep:
For i = 1 To soNhom 'Dieu chinh so nu
If aTK(i, 2) < nMin Or aTK(i, 2) > nMax Then 'Nhom dieu chinh Tang HS Nu
t = soHS + 1
For r = 1 To soNhom
If t > aTK(r, 2) Then
t = aTK(r, 2)
iDC = r 'nhom co so Nu it nhat
End If
Next r
t = 0
For r = 1 To soNhom
If t < aTK(r, 2) Then
t = aTK(r, 2)
k = r 'nhom co so nu nhieu nhat
End If
Next r
tmp = Empty
TroLai:
For r = 1 To soHS
If res(r, 1) = i And Len(arr(r, 1)) <> 2 Then 'Nhom dieu chinh Tang HS Nu và HS Nam
hl = res(r, 2) 'Hoc luc
If InStr(1, tmp, hl) = 0 Then
tmp = tmp & hl
For c = 1 To soHS
If Len(arr(c, 1)) = 2 And res(c, 1) = k And res(c, 2) = hl Then 'HS Nu và nhom co Nu nhieu nhat và cung Hoc luc
t = res(c, 1)
res(c, 1) = res(r, 1)
res(r, 1) = t
aTK(iDC, 2) = aTK(iDC, 2) + 1
aTK(t, 2) = aTK(t, 2) - 1
GoTo DieuChinhTiep
End If
Next c
If c > soHS Then GoTo TroLai
End If
End If
Next r
End If
Next i
sh.Range("F2").Resize(soHS, 2) = res
Call ThongKe(sh, res, aTK, soHS) 'Bang Thong ke ket qua phan nhom
End Sub
Sub ThongKe(sh, res, aTK, soHS)
'aTK co 7 Cot:Nhom, So Hoc Sinh, So Nu, Hoc luc A, B, C, D
Dim i&, r&, c&
For i = 1 To soHS
r = res(i, 1)
c = res(i, 2) + 2
aTK(r, 1) = aTK(r, 1) + 1
aTK(r, c) = aTK(r, c) + 1
Next i
For i = 1 To UBound(aTK)
aTK(i, 0) = i
Next i
sh.Range("I2").Resize(soHS, 7).ClearContents
sh.Range("I2").Resize(UBound(aTK), 7) = aTK
End Sub
Sub TaoMangNgauNhien(aRnd, ByVal N)
Dim i&, t&, r&
ReDim aRnd(1 To N)
For i = 1 To N
r = Int(Rnd * N) + 1
If aRnd(r) = 0 Then t = r Else t = aRnd(r)
If aRnd(N) = 0 Then aRnd(r) = N Else aRnd(r) = aRnd(N)
aRnd(N) = t
N = N - 1
Next i
End Sub