ExcelHome技术论坛

 找回密码
 免费注册

QQ登录

只需一步,快速开始

快捷登录

搜索
EH技术汇-专业的职场技能充电站 妙哉!函数段子手趣味讲函数 Excel服务器-会Excel,做管理系统 效率神器,一键搞定繁琐工作
HR薪酬管理数字化实战 Excel 2021函数公式学习大典 Excel数据透视表实战秘技 打造核心竞争力的职场宝典
让更多数据处理,一键完成 数据工作者的案头书 免费直播课集锦 ExcelHome出品 - VBA代码宝免费下载
用ChatGPT与VBA一键搞定Excel WPS表格从入门到精通 Excel VBA经典代码实践指南
楼主: fanchunke1991

[求助] 求助:怎么利用VBA实现排列组合,进行分组排序?谢谢!

  [复制链接]

TA的精华主题

TA的得分主题

发表于 2014-7-24 22:40 | 显示全部楼层
[广告] VBA代码宝 - VBA编程加强工具 · VBA代码随查随用  · 内置多项VBA编程加强工具       ★ 免费下载 ★      ★使用手册
感觉属于碰运气的办法,分一次班,要点几千次。代码有待修改。

TA的精华主题

TA的得分主题

发表于 2014-7-25 10:53 | 显示全部楼层
[广告] Excel易用宝 - 提升Excel的操作效率 · Excel / WPS表格插件       ★免费下载 ★       ★ 使用帮助
张雄友 发表于 2014-7-24 22:40
感觉属于碰运气的办法,分一次班,要点几千次。代码有待修改。

代码确实有很大的改善空间
最起码不用点几千次是可以做到的,但这样长的运算时间又是个问题

TA的精华主题

TA的得分主题

发表于 2014-7-29 09:39 | 显示全部楼层
张雄友 发表于 2014-7-24 22:40
感觉属于碰运气的办法,分一次班,要点几千次。代码有待修改。

只要理
  1. Sub tt()
  2.     Dim xb$, each_room_p&
  3.     Range("e2:e65536").ClearContents
  4.      each_room_p = Val(InputBox("定义多少人一间宿舍", "你想", 12))
  5.     xb = "男"
  6.     test xb, each_room_p
  7.     xb = "女"
  8.     test xb, each_room_p
  9. End Sub
  10. Sub test(ByVal xb$, ByVal each_room_p&)
  11. '将学校按可安排的宿舍的盈余量升序排序,每次依此排序安排好一个宿舍
  12. '当盈余量为0时,代表每次必须分配该校的学生
  13. '当出现当盈余量<0的情况时,说明无法满足同宿舍没有来自同校的学生
  14.     Dim ar, n&, i&, j&, k&, d, e, br(), cr(), x&, y&
  15.     Set d = CreateObject("scripting.dictionary")
  16.     Set e = CreateObject("scripting.dictionary")
  17.     n = Range("a65536").End(3).Row
  18.     ar = Range("a2:e" & n)
  19.     For i = 1 To UBound(ar)
  20.         If ar(i, 4) = xb Then
  21.             If d(ar(i, 3)) = "" Then d(ar(i, 3)) = d.Count
  22.             e(ar(i, 3)) = e(ar(i, 3)) + 1
  23.         End If
  24.     Next
  25.     n = Application.Max(e.items)
  26.     ReDim br(0 To n, 1 To d.Count), cr(1 To d.Count, 1 To 2)
  27.     n = Application.RoundUp(Application.Sum(e.items) / each_room_p, 0)
  28.     For i = 1 To UBound(ar)
  29.         If ar(i, 4) = xb Then
  30.             x = d(ar(i, 3))    '学校序号
  31.             br(0, x) = br(0, x) + 1    '学校总人数
  32.             br(br(0, x), x) = i    '记录学生的位置号
  33.         End If
  34.     Next
  35.     For i = 1 To UBound(br, 2)
  36.         cr(i, 1) = i: cr(i, 2) = n - br(0, i)
  37.         If cr(i, 2) < 0 Then MsgBox xb & "生无法满足同宿舍人员来自不同学校": Exit Sub
  38.     Next
  39.     For i = 1 To n
  40.         paixu cr
  41.         For j = 1 To each_room_p
  42. '            If (i - 1) * each_room_p + j > Application.Sum(e.items) Then Exit For
  43.             x = br(0, cr(j, 1))
  44.             y = br(x, cr(j, 1))
  45.             If x = 0 Then Exit For
  46.             ar(y, 5) = xb & "舍" & Format(i, "000")
  47.             x = x - 1
  48.             If x = 0 Then
  49.                 cr(j, 2) = n
  50.             End If
  51.             br(0, cr(j, 1)) = x
  52.         Next
  53.         For k = j To UBound(cr)    '本轮未分配的学校,宿舍盈余-1
  54.             cr(k, 2) = cr(k, 2) - 1
  55.             If cr(k, 2) < 0 And i < n Then
  56.                 MsgBox xb & "生无法满足同宿舍人员来自不同学校": Exit Sub
  57.             End If
  58.         Next
  59.     Next
  60.     Range("a2").Resize(UBound(ar), UBound(ar, 2)) = ar
  61. End Sub
  62. Sub paixu(t())
  63.     Dim i&, j&, x
  64.     For i = UBound(t) - 1 To 1 Step -1
  65.         For j = 1 To i
  66.             If t(j, 2) >= t(j + 1, 2) Then '不稳定排序以实现随机性
  67.                 x = t(j, 2): t(j, 2) = t(j + 1, 2): t(j + 1, 2) = x
  68.                 x = t(j, 1): t(j, 1) = t(j + 1, 1): t(j + 1, 1) = x
  69.             End If
  70.         Next
  71.     Next
  72. End Sub
复制代码
论上可以分配,就一定可以分好,要更好的随机性,可以将初始名单乱序后在运行

评分

1

查看全部评分

TA的精华主题

TA的得分主题

发表于 2014-7-29 18:41 | 显示全部楼层
yangyangzhifeng 发表于 2014-7-29 09:39
只要理论上可以分配,就一定可以分好,要更好的随机性,可以将初始名单乱序后在运行

如执行宏,输入14,就是每个宿舍住14人时,女生宿舍无法满足来自不同的学校。这个不能满足,是指个别宿舍无法满足的,但是个别宿舍还是可以满足的。能不能把可以满足的宿舍分出来,不能满足的就最后安排在一间宿舍?

TA的精华主题

TA的得分主题

发表于 2014-7-29 20:43 | 显示全部楼层
张雄友 发表于 2014-7-29 18:41
如执行宏,输入14,就是每个宿舍住14人时,女生宿舍无法满足来自不同的学校。这个不能满足,是指个别宿舍 ...

If cr(i, 2) < 0 Then MsgBox xb & "生无法满足同宿舍人员来自不同学校": Exit Sub
改成
If cr(i, 2) < 0 Then MsgBox xb & "生无法满足同宿舍人员来自不同学校"

TA的精华主题

TA的得分主题

发表于 2014-7-29 20:55 | 显示全部楼层
yangyangzhifeng 发表于 2014-7-29 20:43
If cr(i, 2) < 0 Then MsgBox xb & "生无法满足同宿舍人员来自不同学校": Exit Sub
改成
If cr(i, 2) < ...

不对,有一个人无法安排。透视表验证是:9,1,应该是10 才对。
女舍006  9

空白       1


女舍006 为10才对。

不对.rar

27.81 KB, 下载次数: 2

TA的精华主题

TA的得分主题

发表于 2014-7-30 00:01 | 显示全部楼层
本帖最后由 yangyangzhifeng 于 2014-7-30 07:02 编辑
张雄友 发表于 2014-7-29 20:55
不对,有一个人无法安排。透视表验证是:9,1,应该是10 才对。
女舍006  9

试试看
  1. Sub yangyangzhifeng() 'http://club.excelhome.net/thread-895293-12-1.html
  2. '只要理论上可以分配,就一定可以分好,要更好的随机性,可以将初始名单乱序后再运行!
  3.     Dim xb$, each_room_p&

  4.     Range("E2:E65536").ClearContents
  5.      each_room_p = Val(InputBox("定义多少人一间宿舍", "你想", 14))
  6.     xb = "男"
  7.     test xb, each_room_p
  8.     xb = "女"
  9.     test xb, each_room_p
  10.     ActiveSheet.PivotTables("数据透视表1").PivotCache.Refresh '刷新数据透视表

  11. End Sub
  12. Sub test(ByVal xb$, ByVal each_room_p&)
  13. '将学校按可安排的宿舍的盈余量升序排序,每次依此排序安排好一个宿舍
  14. '当盈余量为0时,代表每次必须分配该校的学生
  15. '当出现当盈余量<0的情况时,说明无法满足同宿舍没有来自同校的学生
  16.     Dim ar, n&, i&, j&, k&, d, e, br(), cr(), dr&(), x&, y&
  17.     Set d = CreateObject("scripting.dictionary")
  18.     Set e = CreateObject("scripting.dictionary")
  19.     n = Range("A65536").End(3).Row
  20.     ar = Range("A2:E" & n)    '!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  21.     For i = 1 To UBound(ar)
  22.         If ar(i, 4) = xb Then    '第四列为性别!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  23.             If d(ar(i, 3)) = "" Then d(ar(i, 3)) = d.Count    '对第三列进行不重复值设置!!!!!!!!!!!!!!!!!!!!!!!!!!
  24.             e(ar(i, 3)) = e(ar(i, 3)) + 1    '累加变量!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  25.         End If
  26.     Next
  27.     n = Application.Max(e.items)
  28.     ReDim br(0 To n, 1 To d.Count), cr(1 To d.Count, 1 To 2)
  29.     n = Application.RoundUp(Application.Sum(e.items) / each_room_p, 0)
  30.     ReDim dr(1 To n)    '记录宿舍空位
  31.     For i = 1 To UBound(ar)
  32.         If ar(i, 4) = xb Then    '第四列为性别!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  33.             x = d(ar(i, 3))    '学校序号!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  34.             br(0, x) = br(0, x) + 1    '学校总人数
  35.             br(br(0, x), x) = i    '记录学生的位置号
  36.         End If
  37.     Next
  38.     For i = 1 To UBound(br, 2)
  39.         cr(i, 1) = i: cr(i, 2) = n - br(0, i)
  40.         'If cr(i, 2) < 0 Then MsgBox xb & "生无法满足同宿舍人员来自不同学校": Exit Sub
  41.         '如执行宏,输入14,就是每个宿舍住14人时,女生宿舍无法满足来自不同的学校。
  42.         '这个不能满足,是指个别宿舍无法满足的,但是个别宿舍还是可以满足的,
  43.         '能不能把可以满足的宿舍分出来,不能满足的就最后安排在一间宿舍?
  44.         'If cr(i, 2) < 0 Then MsgBox xb & "生无法满足同宿舍人员来自不同学校": Exit Sub
  45.         '改成
  46.         If cr(i, 2) < 0 Then MsgBox xb & "生无法满足同宿舍人员来自不同学校"
  47.     Next
  48.     For i = 1 To n
  49.         paixu cr
  50.         For j = 1 To each_room_p
  51.             x = br(0, cr(j, 1))
  52.             y = br(x, cr(j, 1))
  53.             If x = 0 Then dr(i) = each_room_p - j + 1: Exit For
  54.             ar(y, 5) = xb & "舍" & Format(i, "000")    '在第五列生成宿舍号!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  55.             x = x - 1
  56.             If x = 0 Then
  57.                 cr(j, 2) = n
  58.             End If
  59.             br(0, cr(j, 1)) = x
  60.         Next
  61.         For k = j To UBound(cr)    '本轮未分配的学校,宿舍盈余-1
  62.             cr(k, 2) = cr(k, 2) - 1
  63.         Next
  64.     Next
  65.     If Application.Sum(Application.Index(br, 1, 0)) > 0 Then
  66.         i = 0: j = 0
  67.         Do
  68.             Do
  69.                 i = i + 1
  70.                 If br(0, i) > 0 Then x = br(0, i): Exit Do
  71.                 If i = d.Count Then i = 0
  72.             Loop
  73.             Do
  74.                 j = j + 1
  75.                 If dr(j) > 0 Then Exit Do
  76.             Loop
  77.             ar(br(x, i), 5) = xb & "舍" & Format(j, "000")
  78.             x = x - 1: br(0, i) = x
  79.             If Application.Sum(Application.Index(br, 1, 0)) = 0 Then Exit Do
  80.             j = j Mod n
  81.             i = i Mod d.Count
  82.         Loop
  83.     End If
  84.     Range("A2").Resize(UBound(ar), UBound(ar, 2)) = ar
  85. End Sub
  86. Sub paixu(t())
  87.     Dim i&, j&, x
  88.     For i = UBound(t) - 1 To 1 Step -1
  89.         For j = 1 To i
  90.             If t(j, 2) >= t(j + 1, 2) Then '不稳定排序以实现随机性
  91.                 x = t(j, 2): t(j, 2) = t(j + 1, 2): t(j + 1, 2) = x
  92.                 x = t(j, 1): t(j, 1) = t(j + 1, 1): t(j + 1, 1) = x
  93.             End If
  94.         Next
  95.     Next
  96. End Sub
复制代码

评分

1

查看全部评分

TA的精华主题

TA的得分主题

发表于 2014-7-30 06:44 | 显示全部楼层
yangyangzhifeng 发表于 2014-7-30 00:01
试试看

如执行宏,输入16,就是每个宿舍住16人时,这样男女都无法分配了。不正确,理论上,男女还是可以分配的。(113楼代码男生都可以分配)

不对2.rar

27.65 KB, 下载次数: 8

TA的精华主题

TA的得分主题

发表于 2014-7-30 07:06 | 显示全部楼层
[广告] VBA代码宝 - VBA编程加强工具 · VBA代码随查随用  · 内置多项VBA编程加强工具       ★ 免费下载 ★      ★使用手册
张雄友 发表于 2014-7-30 06:44
如执行宏,输入16,就是每个宿舍住16人时,这样男女都无法分配了。不正确,理论上,男女还是可以分配的。 ...

117楼编辑过了,再试试看。因为你写了On error resume goto 语句,而代码有一处错误,所以造成没有输出。

TA的精华主题

TA的得分主题

发表于 2014-7-30 07:43 | 显示全部楼层
yangyangzhifeng 发表于 2014-7-30 07:06
117楼编辑过了,再试试看。因为你写了On error resume goto 语句,而代码有一处错误,所以造成没有输出。

是的,但是有个问题,如果执行,点取消时,会出现错误,除数为0,怎么不让这个对话框出现?
您需要登录后才可以回帖 登录 | 免费注册

本版积分规则

手机版|关于我们|联系我们|ExcelHome

GMT+8, 2024-11-18 21:29 , Processed in 0.040147 second(s), 12 queries , Gzip On, MemCache On.

Powered by Discuz! X3.4

© 1999-2023 Wooffice Inc.

沪公网安备 31011702000001号 沪ICP备11019229号-2

本论坛言论纯属发表者个人意见,任何违反国家相关法律的言论,本站将协助国家相关部门追究发言者责任!     本站特聘法律顾问:李志群律师

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