Excel精英培训网

 找回密码
 注册
数据透视表40+个常用小技巧,让你一次学会!
查看: 3242|回复: 7

[已解决]按类随机排序

[复制链接]
发表于 2015-4-21 13:54 | 显示全部楼层 |阅读模式
本帖最后由 abc153 于 2015-4-25 10:42 编辑

按类随机排序.zip (2.47 KB, 下载次数: 15)
excel精英培训的微信平台,每天都会发送excel学习教程和资料。扫一扫明天就可以收到新教程
发表于 2015-4-21 16:38 | 显示全部楼层
  1. Sub Macro1()
  2. Dim arr, brr, crr, d, i&, j&, k%, n&, s&, y&
  3. Set d = CreateObject("scripting.dictionary")
  4. arr = Range("d5:i" & Range("d65536").End(xlUp).Row + 1)
  5. n = 1
  6. For i = 2 To UBound(arr)
  7.     If arr(i, 1) <> arr(n, 1) Then d(arr(i - 1, 1)) = n + 4 & "," & i + 3: n = i
  8. Next
  9. a = d.keys: b = d.items
  10. For i = 0 To d.Count - 1
  11.     x = Split(b(i), ",")
  12.     brr = Range("d" & Val(x(0)) & ":i" & Val(x(1)))
  13.     ReDim crr(1 To UBound(brr), 1 To UBound(brr, 2))
  14.     n = UBound(brr)
  15.     For j = 1 To n
  16. 100:
  17.         s = n - j + 1
  18.         y = Int(Rnd * s + 1)
  19.         If j > 1 Then
  20.             If crr(j - 1, 6) = brr(y, 6) Then GoTo 100
  21.         End If
  22.         For k = 1 To UBound(brr, 2)
  23.             crr(j, k) = brr(y, k)
  24.             brr(y, k) = brr(s, k)
  25.         Next
  26.     Next
  27.     Cells(Val(x(0)), "k").Resize(UBound(crr), UBound(crr, 2)) = crr
  28. Next
  29. End Sub
复制代码
回复

使用道具 举报

发表于 2015-4-21 16:46 | 显示全部楼层
遇到死循环时(如随机排序,最后两人都是一班),按ESC强行中断代码

按类随机排序.zip

9.66 KB, 下载次数: 7

回复

使用道具 举报

发表于 2015-4-21 17:29 | 显示全部楼层
如果班级相同,可多运行一次代码,楼主要求随机排序的 只要保证排序的班级错开就好了

按类随机排序.zip

14.14 KB, 阅读权限: 1, 下载次数: 5

回复

使用道具 举报

发表于 2015-4-21 20:25 | 显示全部楼层
防死机代码
  1. Sub tt()
  2.     arr = [d4:i23]
  3.     c = UBound(arr, 2)
  4.     Randomize
  5. bb:
  6.     t1 = Timer
  7.     r = UBound(arr)
  8.     brr = arr
  9.     For i = 2 To UBound(arr)
  10. aa:
  11.         p = Int((r - 1) * Rnd + 2)
  12.         If arr(p, 6) <> brr(i - 1, 6) Then
  13.             For j = 1 To c
  14.                 brr(i, j) = arr(p, j)
  15.                 arr(p, j) = arr(r, j)
  16.             Next
  17.             r = r - 1
  18.         Else
  19.             If Timer - t1 > 1 Then
  20.                 s = s + 1
  21.                 If s > 3 Then MsgBox "请重新点击": Exit Sub
  22.                 GoTo bb
  23.             End If
  24.             GoTo aa
  25.         End If
  26.     Next
  27.     [k4].Resize(UBound(brr), UBound(brr, 2)) = brr
  28. End Sub
复制代码

按类随机排序.zip

10.79 KB, 下载次数: 5

回复

使用道具 举报

 楼主| 发表于 2015-4-22 12:20 | 显示全部楼层
谢谢各位老师,您们写的代码都很卡,有时还无法运行!
回复

使用道具 举报

发表于 2015-4-22 14:36 | 显示全部楼层
试试这个,应该不会卡:
注意:用了字典,请自行引用;J列做了辅助列,故J列中不要有内容
Sub test()
Dim d1 As New Dictionary, d2 As New Dictionary, ar1(), ar2()
i1% = [g65536].End(3).Row
If i1 < 6 Then Exit Sub
[j5].Resize(i1 - 4) = "=rand()"
Range("g4").Resize(i1 - 3, 4).Sort [i4], , [j4], , , , , xlYes
[j5].Resize(i1 - 4).ClearContents
ar1 = Range("g5").Resize(i1 - 4, 3).Value
ReDim ar2(1 To i1 - 4, 1 To 3)
For i1 = 1 To UBound(ar1)
    d1(ar1(i1, 3)) = i1
    d2(ar1(i1, 3)) = d2(ar1(i1, 3)) + 1
Next
For i1 = 1 To UBound(ar1)
    maxr% = 0
    For Each stmp In d1.Keys
        If bj$ <> stmp Then If maxr% < d2(stmp) Then maxr = d2(stmp): stmp2$ = stmp
    Next
    If maxr Then bj = stmp2
    r = r% + 1
    ar2(r, 1) = ar1(d1(bj), 1)
    ar2(r, 2) = ar1(d1(bj), 2)
    ar2(r, 3) = ar1(d1(bj), 3)
    d1(bj) = d1(bj) - 1
    d2(bj) = d2(bj) - 1
Next
[m5].Resize(UBound(ar2), 3) = ar2
End Sub
回复

使用道具 举报

发表于 2015-4-23 12:58 | 显示全部楼层    本楼为最佳答案   
本帖最后由 wcymiss 于 2015-4-23 13:03 编辑

请楼主测试:结果放在sheet2表中了:
  1. Option Explicit

  2. Sub Main()
  3.     Dim arrData()
  4.     Dim i As Long
  5.     Dim startRow As Long
  6.     Dim endRow As Long
  7.    
  8.     With Sheet1
  9.         arrData = .Range("D5:I" & .Cells(.Rows.Count, "D").End(xlUp).Row + 1).Value
  10.     End With
  11.    
  12.     startRow = 1
  13.     For i = 2 To UBound(arrData)
  14.         If arrData(i, 1) <> arrData(i - 1, 1) Then
  15.             endRow = i - 1
  16.             Call MySort(arrData, startRow, endRow, 6)
  17.             startRow = i
  18.         End If
  19.     Next
  20.    
  21.     Sheet2.Cells.Clear
  22.     Sheet2.Range("a1").Resize(UBound(arrData), UBound(arrData, 2)).Value = arrData
  23. End Sub

  24. Sub MySort(arrData, startRow As Long, endRow As Long, KeyColumn As Long)
  25.     Dim i As Long
  26.     Dim j As Long
  27.     Dim RandNum As Long
  28.    
  29.     '洗牌随机
  30.     Randomize
  31.     For i = endRow To startRow Step -1
  32.         RandNum = Int(Rnd * (i - startRow + 1) + startRow)
  33.         Call Exchange(arrData, RandNum, i)
  34.     Next
  35.    
  36.     '顺序倒序选择交换
  37.     '顺序
  38.     For i = startRow + 1 To endRow - 1
  39.         If arrData(i, KeyColumn) = arrData(i - 1, KeyColumn) Then
  40.             For j = i + 1 To endRow
  41.                 If arrData(j, KeyColumn) <> arrData(i, KeyColumn) Then
  42.                     Call Exchange(arrData, j, i)
  43.                     Exit For
  44.                 End If
  45.             Next
  46.         End If
  47.     Next
  48.    
  49.     '倒序
  50.     For i = endRow - 1 To startRow + 1 Step -1
  51.         If arrData(i, KeyColumn) = arrData(i + 1, KeyColumn) Then
  52.             For j = i - 1 To startRow Step -1
  53.                 If arrData(j, KeyColumn) <> arrData(i, KeyColumn) Then
  54.                     Call Exchange(arrData, j, i)
  55.                     Exit For
  56.                 End If
  57.             Next
  58.         End If
  59.     Next
  60. End Sub

  61. Sub Exchange(arrData, row1 As Long, row2 As Long)
  62.     Dim Temp
  63.     Dim j As Long
  64.     For j = 1 To UBound(arrData, 2)
  65.         Temp = arrData(row1, j)
  66.         arrData(row1, j) = arrData(row2, j)
  67.         arrData(row2, j) = Temp
  68.     Next
  69. End Sub
复制代码
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

小黑屋|手机版|Archiver|Excel精英培训 ( 豫ICP备11015029号 )

GMT+8, 2024-5-20 15:08 , Processed in 0.271072 second(s), 11 queries , Gzip On, Yac On.

Powered by Discuz! X3.4

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表