ExcelTip.Net留存知识帖 ---【注:附件之前被网盘供应商清空后,现已修复-现已修复-现已修复为本地下载!】
现在位置:首页 > E问E答 > Excel VBA > 如何用VBA代码实现考场排序时不将同一班级学生排列在一起?

如何用VBA代码实现考场排序时不将同一班级学生排列在一起?

作者:绿色风 分类: 时间:2022-08-17 浏览:129
楼主
kevinchengcw
Q: 如何用VBA代码实现考场排序时不将同一班级学生排列在一起?
A: 本例利用一个提问帖演示一种排列及判断的方式,代码如下:
  1. Sub test()
  2. Dim M, N, I As Long
  3. Dim Dic, Arr
  4. Dim Same As Boolean
  5. Dim Str As String
  6. Application.ScreenUpdating = False  '关闭屏幕刷新以提高处理速度
  7. Set Dic = CreateObject("scripting.dictionary")   '创建字典项目,本例中会利用字典项目的易于添加删除的特性将已排过的删除掉
  8. With Worksheets("sheet1")  '在数据区内循环,并将各项添加到字典内
  9.     For N = 5 To .Cells(.Rows.Count, 2).End(3).Row  '循环区域为从第5行起到最后一行
  10.         Str = .Cells(N, 4).Value & vbTab & .Cells(N, 2).Value & vbTab & .Cells(N, 3).Value  '利用BCD三列的内容做为item项,为了方便比较班级,将D列的内容放在最前面
  11.         Dic.Add CStr(.Cells(N, 1).Value), Str  '利用序号作为key,组合好的字段为item添加字典项目
  12.     Next N
  13. End With
  14. With Worksheets("sheet2")  '利用sheet2进行数据处理
  15.     Do While Dic.Count > 0  '循环直至字典项目为0,即处理完全部项目
  16.         Arr = Dic.keys  '将字典的keys赋值给数组
  17.         Same = True  '初始化变量same为真,用于判断字典中剩余项目是否都是同一个班级,如果是则same继续为真值,否则为假
  18.         For N = LBound(Arr) To UBound(Arr)  '循环数组来提取对应的字典项,提取班级并进行比较
  19.             If Split(Dic(Arr(0)), vbTab)(0) <> Split(Dic(Arr(N)), vbTab)(0) Then  '如果有不相同的班级存在,则
  20.                 Same = False   '变量same值为假
  21.                 Exit For   '退出循环
  22.             End If
  23.         Next N
  24.         If Same = False Then  '当变量same值为假时,即存在不相同的班级时
  25.             For N = LBound(Arr) To UBound(Arr)  '循环数组中各项
  26.                 If Dic.exists(Arr(N)) Then   '如果存在对应的字典项则
  27.                     If Arr(N) = 1 Then   '如果数组的值为1(即第一次执行,此时因sheet2中无初始数据,故要专门执行一次)
  28.                         .Cells(1, 1) = 1
  29.                         .Cells(1, 2) = Split(Dic(Arr(N)), vbTab)(1)
  30.                         .Cells(1, 3) = Split(Dic(Arr(N)), vbTab)(2)
  31.                         .Cells(1, 4) = Split(Dic(Arr(N)), vbTab)(0)
  32.                         Dic.Remove Arr(N)  '执行过后删除对应的字典项
  33.                     Else  '如果不是第一次执行,则
  34.                         If Split(Dic(Arr(N)), vbTab)(0) <> .Cells(.Cells(.Rows.Count, 1).End(3).Row, 4).Value Then   '判断当前字典项的班级与已有的最后一个班级是否不同,如不同则将对应内容写到对应单元格中
  35.                             .Cells(.Cells(.Rows.Count, 1).End(3).Row + 1, 1) = .Cells(.Rows.Count, 1).End(3).Row + 1
  36.                             .Cells(.Cells(.Rows.Count, 1).End(3).Row, 2) = Split(Dic(Arr(N)), vbTab)(1)
  37.                             .Cells(.Cells(.Rows.Count, 1).End(3).Row, 3) = Split(Dic(Arr(N)), vbTab)(2)
  38.                             .Cells(.Cells(.Rows.Count, 1).End(3).Row, 4) = Split(Dic(Arr(N)), vbTab)(0)
  39.                             Dic.Remove Arr(N)   '并删除当前字典项
  40.                         End If
  41.                     End If
  42.                 End If
  43.             Next N
  44.         Else   '如果same值为真时,即现有字典项内内容全部为同一班级时,则
  45.             For N = LBound(Arr) To UBound(Arr)   '循环字典项
  46.                 For I = 2 To .Cells(.Rows.Count, 1).End(3).Row    '循环数据区
  47.                     If .Cells(I - 1, 4) <> Split(Dic(Arr(N)), vbTab)(0) And .Cells(I, 4) <> Split(Dic(Arr(N)), vbTab)(0) Then  '如果数据区当前行的与上一行的班级与字典当前项不同,则在当前行处插入一行,写入当前字典项内容到对应单元格中
  48.                         .Rows(I).Insert
  49.                         .Cells(I, 2) = Split(Dic(Arr(N)), vbTab)(1)
  50.                         .Cells(I, 3) = Split(Dic(Arr(N)), vbTab)(2)
  51.                         .Cells(I, 4) = Split(Dic(Arr(N)), vbTab)(0)
  52.                         Dic.Remove Arr(N)  '并删除当前字典项
  53.                         Exit For  '跳出循环,以便循环到下一个字典项
  54.                     End If
  55.                     If Dic.Count = 0 Then Exit For  '如果字典项计数为0时跳出循环,以免出错
  56.                 Next I
  57.             Next N
  58.         End If
  59.     Loop
  60.     Worksheets("sheet1").[b5].Resize(.Cells(.Rows.Count, 2).End(3).Row, 3) = .[b1].Resize(.Cells(.Rows.Count, 2).End(3).Row, 3).Value  '将已排好的内容写回sheet1的原数据区
  61.     .Cells.Clear  '清空sheet2中的全部内容
  62. End With
  63. Set Dic = Nothing    '清空字典项目
  64. Application.ScreenUpdating = True  '打开屏幕刷新
  65. End Sub

方法解释如下:
利用字典记录全部数据,逐个循环数据,当班级不相同时写入数据,相同时跳过,直至剩余数据全部为同一班级时,在已排序范围内循环,如果有两行班级不同,且与现有数据班级也不同的行时,则将现有数据插入到两个班级之间,如此直至数据全部排列完毕。
附示例文件。
考试排序,前后不同班.rar
2楼
cola
先收藏,以备将来不时之需。
另外,再提个建议,因为通常安排考场时是安排几纵几横的,也要求相邻座位不得有同单位(或班级)的考生,前后左右都是非本单位(或班级)的考生,如果楼主可以在最初时让用户选择几纵几横,然后再产生一个几纵几横的座位图那就更好了。
3楼
cola
二楼提议非常正确,得要前后左右不同班级(或单位),另外还得几纵几横。
4楼
icenotcool


5楼
wumin88838
需要多学习研究下

免责声明

有感于原ExcelTip.Net留存知识的价值及部分知识具有的时间限定性因素, 经与ExcelTip.Net站长Apolloh商议并征得其同意, 现将原属ExcelTip.Net的知识帖采集资料于本站点进行展示, 供有需要的人士查询使用,也慰缅曾经的论坛时代。 所示各个帖子的原作者如对版权有异议, 可与本人沟通提出,或于本站点留言,我们会尽快处理。 在此,感谢ExcelTip.Net站长Apolloh的支持,感谢本站点所有人**绿色风(QQ:79664738)**的支持与奉献,特此鸣谢!
------本人网名**KevinChengCW(QQ:1210618015)**原ExcelTip.Net总版主之一

评论列表
sitemap