ExcelTip.Net留存知识帖 ---【注:附件之前被网盘供应商清空后,现已修复-现已修复-现已修复为本地下载!】
现在位置:首页 > 我的酷贴 > Excel VBA > VBA 代码不是多而是精

VBA 代码不是多而是精

作者:绿色风 分类: 时间:2022-08-18 浏览:105
楼主
研究研究
原作者要求优化VBA代码

q:我这儿有一个VBA自定义多方式排序的代码,很实用,但存在着一个问题,就是,少数据时,排序很快,如果多数据时,就很慢,甚至程序无响应。

A:但是原代码的思路过于复杂。方法和手段过于绕弯经本人测试。排序一个自定义名称为 【职称】整整用了我488.秒以上
经优化后才2秒左右


Q:
  1. Sub 自定义排序()
  2. Dim KeyWD, iKey, iUseKey
  3. Dim sh As Worksheet
  4. Dim c As Range, cS As Range, cZ As Range, cX As Range
  5. Dim r&, rE&, rZ&, col%, strX$, i&, iTimer
  6. Set KeyWD = CreateObject("Scripting.Dictionary")
  7. On Error Resume Next

  8. '-----需改动的变量------开始
  9. '-----自定义的序列,这里还可以增加自定义排序的顺序,可以增加多项。
  10. KeyWD("科室") = "外妇科,手术室,内儿科,西医科,中医科,耳鼻喉科,放射科,检验科,B超室,口腔科,针灸科,西药房,中药房,收费室,疾控科,合管办,后勤科"
  11. KeyWD("性别") = "男,女"
  12. KeyWD("级别") = "中级,初级"
  13. KeyWD("受聘专业") = "医生,护士"
  14. strX = "序号" '序号,用处是,自动查找,工作有中,序号位置,但一个工作表中,不能有第二个序号,字符出现,否则,不能正确的重新编写序号,本句目的是,不会因为列与行的改变而改变编号位置。
  15. Set sh = ActiveSheet '操作的工作表,不需要设置操作工作表变量,操作的就是当前工作表。
  16. '-----需改动的变量------结束

  17. Set cS = Application.InputBox("请选择要排序列的标题单元格:", Type:=8)
  18. 'If cS Is Nothing Then MsgBox "取消排序!": Exit Sub '这一句,是表示有“取消排序”提示。
  19. If cS Is Nothing Then: Exit Sub '这一句,是表示无“取消排序”提示。
  20. Set cX = cS.EntireRow.Cells.Find(strX, , xlValues, xlWhole)
  21. Set cS = cS.Cells(2, 1)

  22. Application.ScreenUpdating = False
  23. On Error GoTo 1000
  24. iTimer = Timer
  25. With sh
  26. r = cS.Row '开始排序的行数
  27. col = cS.Column '排序关键字所在列
  28. rE = .UsedRange.Row + .UsedRange.Rows.Count - 1 '末**
  29. For i = rE To r Step -1
  30. If Application.WorksheetFunction.CountA(.Rows(i)) Then
  31. rE = i
  32. Exit For
  33. End If
  34. Next
  35. 'If MsgBox(rE, vbOKCancel) <> vbOK Then GoTo 1000 '此句为调试代码时使之用。
  36. iUseKey = cS.Offset(-1).Value

  37. '----先用系统自带的排序
  38. .Rows(r & ":" & rE).Sort Key1:=cS, Order1:=xlAscending


  39. If KeyWD.Exists(iUseKey) Then
  40. iKey = Split(KeyWD(iUseKey), ",") '存储;自定义序列。“,”这个表示自定义排序的分隔符号,同变量是的“,”,也就是把排序的关健字的分隔符,以前(狂人狂笑笑人狂)网友是用“|”来分隔的,由于,在输入时,不好输入,所以改成了“智能五笔”输入状态下的“,”符号便于输入。
  41. Else
  42. GoTo 2000
  43. End If
  44. '----排序,有关键字部分
  45. For i = LBound(iKey) To UBound(iKey)
  46. Set c = .Columns(col).Find(iKey(i), cS.Offset(-1), xlValues, xlWhole)
  47. If Not c Is Nothing Then
  48. Set cZ = c
  49. rZ = 1
  50. Do While c.Offset(1) = c
  51. rZ = rZ + 1
  52. Set c = c.Offset(1)
  53. Loop
  54. If cZ.Row <> r Then
  55. cZ.EntireRow.Resize(rZ).Cut
  56. cS.EntireRow.Insert Shift:=xlDown
  57. End If
  58. r = r + rZ
  59. Set cS = .Cells(r, col)
  60. End If
  61. Next
  62. If r > rE Then GoTo 2000
  63. '----排序,无关键字部分
  64. rZ = r
  65. For r = r To rE
  66. If .Cells(r, col).Value <> "" Then
  67. If r <> rZ Then
  68. sh.Rows(r).Cut
  69. sh.Rows(rZ).Insert Shift:=xlDown
  70. End If
  71. rZ = rZ + 1
  72. End If
  73. Next
  74. 2000:
  75. '----写入序号
  76. If Not cX Is Nothing Then
  77. With cX
  78. For r = 1 To rE - cX.Row
  79. .Offset(r).Value = r
  80. Next
  81. End With
  82. End If
  83. End With
  84. Application.ScreenUpdating = True
  85. MsgBox "排序完成!用时" & Format(Timer - iTimer, "0.0秒") '计算整个排序过程用时多少,如果不需要直接注释掉即可。
  86. Exit Sub
  87. 1000:
  88. Application.ScreenUpdating = True
  89. MsgBox "发生未知错误!请联系作者", vbCritical
  90. End Sub
  91. '-----自定义排序代码------结束



A:
  1. Sub Macro1()

  2. Set cS = Application.InputBox("请选择要排序列的标题单元格:", Type:=8)
  3. If cS Is Nothing Then: Exit Sub
  4. 'Set cS = cS.Cells(2, 1)
  5. r = cS.Row '开始排序的行数
  6. col = cS.Column '排序关键字所在列
  7. iTimer = Timer
  8. Range("C3:BK5003").Sort Key1:=Cells(r, col), Order1:=xlAscending, Header:=xlGuess  '直接用关键字对区域经行排序
  9. MsgBox Timer - iTimer
  10. End Sub

宏_自下定义排序(多数据).rar
2楼
MMonica605
强~

免责声明

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

评论列表
sitemap