ExcelHome技术论坛

 找回密码
 免费注册

QQ登录

只需一步,快速开始

快捷登录

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

[原创] 通过一题十解谈拓宽编程思路

  [复制链接]

TA的精华主题

TA的得分主题

发表于 2013-4-6 08:48 | 显示全部楼层
[广告] VBA代码宝 - VBA编程加强工具 · VBA代码随查随用  · 内置多项VBA编程加强工具       ★ 免费下载 ★      ★使用手册
本帖已被收录到知识树中,索引项:数据类型和基本语句
俗话说:站在什么样的山头唱什么样的山歌。楼主既然是在此发表东东,就是基于VBA的资源而展示其对某一问题的多种解决方法。因此,只要编程的代码少,效率(代码的执行有所下降)还行,代码易于维护,就值得称赞。比如:"字典"的方法,大家对其的运用已经熟能生巧,如果能用"字典"解决的问题(如一楼的问题或者不仅限于此问题),您偏要用"数组"的方法来解决,就会编程的代码多,代码不易于维护。所以说:充分利用本地的资源,较好地解决问题,是非常简单而有效的方法。

TA的精华主题

TA的得分主题

发表于 2013-4-6 10:20 | 显示全部楼层
[广告] VBA代码宝 - VBA编程加强工具 · VBA代码随查随用  · 内置多项VBA编程加强工具       ★ 免费下载 ★      ★使用手册
一味的追求编程技巧,就失去了编程目标

TA的精华主题

TA的得分主题

发表于 2013-4-6 11:07 | 显示全部楼层

TA的精华主题

TA的得分主题

发表于 2013-4-6 11:09 | 显示全部楼层
本帖最后由 香川群子 于 2013-4-6 11:18 编辑
office2008 发表于 2013-4-6 01:17
应该不算完美  
以上数据只有第2和第5 是正确的.


取得A列最大值的方法,经过比较确认,结果大致如下:

A列单元格个数超过200时,直接用工作表函数Application.max([Range])的方法速度效率高。

仅当A列单元格个数<200时,数组For……Next遍历比较方法速度更快一些。
并且有个前提是原始数据已经读入数组了。
(这个条件一般是具备的,即代码本来就需要把原始数据预先读入VBA内存数组使用)

而这时候的时间差异其实是很小的。【就本例来说,数组循环快了 0.000028秒】

……
因此,不是一定要全部工作都必须通过数组搞定的。
我的代码方法kagawa2中的直接Max用法也是可以的。
  1. Sub SpeedTest()
  2.     Dim ii&, nn%, i&, m&, n&
  3.     nn = 4 '指定循环比较次数=10^nn
  4.    
  5.     m = 200 '直接指定A列计算行数(即A列单元格个数)
  6.    
  7.     tms = Timer
  8.     For ii = 1 To 10 ^ nn
  9.         n = Application.max(Range("A1").Resize(m)) '用工作表函数Max直接获取最大值
  10.     Next
  11.     MsgBox "Max " & Format(Timer - tms, "0.000s ") & n


  12.     arr = Range("A1").Resize(m) '单元格内容读入数组,然后才可以比较
  13.     tms = Timer
  14.     For ii = 1 To 10 ^ nn
  15.         For i = 1 To m
  16.             If arr(i, 1) > n Then n = arr(i, 1)   '数组循环遍历比较取得最大值
  17.         Next
  18.     Next
  19.     MsgBox "For " & Format(Timer - tms, "0.000s ") & n
  20.    

  21. End Sub
复制代码

TA的精华主题

TA的得分主题

发表于 2013-4-6 11:21 | 显示全部楼层
香川群子 发表于 2013-4-6 11:09
取得A列最大值的方法,经过比较确认,结果大致如下:

A列单元格个数超过200时,直接用工作表函数App ...

你用vb指针测试一下数组的速度

TA的精华主题

TA的得分主题

发表于 2013-4-6 13:10 | 显示全部楼层

TA的精华主题

TA的得分主题

发表于 2013-4-6 14:12 | 显示全部楼层
[广告] VBA代码宝 - VBA编程加强工具 · VBA代码随查随用  · 内置多项VBA编程加强工具       ★ 免费下载 ★      ★使用手册
学习了.谢谢分享.

TA的精华主题

TA的得分主题

发表于 2013-4-6 16:52 | 显示全部楼层
本帖最后由 香川群子 于 2013-4-6 17:07 编辑
liucqa 发表于 2013-4-6 11:21
你用vb指针测试一下数组的速度


呵呵,如果是用工作表函数Max求VBA内存数组的最大值,
速度显然没有VBA内存数组直接For……Next循环快。(数组循环速度最快)

但是,如果同样使用工作表函数Max,但【求和对象】为【工作表单元格区域】的引用时,
则速度会比VBA内存数组直接For……Next循环【更快】。

这可能不符合很多人的常识,但事实如此。

推测或许Excel在把数据写入工作表单元格内时,已经做了一些数值计算、统计的工作,方便引用。
因此速度加快。
  1. Sub test()
  2.    
  3.     Dim i&, j&, k&, m&, n&
  4.    
  5.     m = 10000 '数据行数m
  6.     n = 100    '数据列数n
  7.     ReDim arr&(1 To m, 1 To n)
  8.     For i = 1 To m
  9.         For j = 1 To n
  10.             arr(i, j) = Rnd * 16777216
  11.         Next
  12.     Next
  13.     [a1].Resize(m, n) = arr '产生随机数并写入工作表【这很重要!】
  14.    
  15.    
  16.     '以下为速度比较:
  17.     Dim ii&, nn&, tms
  18.     nn = 1 '速度比较重复次数nn,可以调整
  19.    
  20.     tms = Timer
  21.     For ii = 1 To nn
  22.         k = Application.Max(arr) '用工作表函数Max检查【VBA数组】的最大值
  23. '        k = WorksheetFunction.Max(arr)
  24.     Next
  25.     MsgBox "工作表Max求数组对象 耗时:" & vbCr & Format(Timer - tms, "0.000s ") & k
  26.    
  27.     tms = Timer
  28.     For ii = 1 To nn
  29.         k = Application.Large(arr, 1) '用工作表函数Large检查【VBA数组】的最大值
  30. '        k = WorksheetFunction.Large(arr, 1)
  31.     Next
  32.     MsgBox "工作表Large求数组对象 耗时:" & vbCr & Format(Timer - tms, "0.000s ") & k
  33.    
  34.     tms = Timer
  35.     For ii = 1 To nn
  36.         k = Application.Large(Range("A1").Resize(m, n), 1) '用工作表函数Large检查【区域】的最大值
  37.     Next
  38.     MsgBox "工作表Large求Range区域 耗时:" & vbCr & Format(Timer - tms, "0.000s ") & k
  39.    
  40.     tms = Timer
  41.     For ii = 1 To nn
  42.         k = Application.Max(Range("A1").Resize(m, n)) '用工作表函数Max检查【区域】的最大值
  43.     Next
  44.     MsgBox "工作表Max求Range区域 耗时:" & vbCr & Format(Timer - tms, "0.000s ") & k
  45.     '因为可以直接利用工作表内容,所以速度提高!
  46.     '推测是数据写入工作表函数的过程中,Excel已经做了很多基础工作,包括求总和所以速度更快。
  47.    
  48.    
  49.     tms = Timer
  50.     For ii = 1 To nn
  51.         k = 0
  52.         For i = 1 To m
  53.             For j = 1 To n
  54.                 If arr(i, j) > k Then k = arr(i, j) '数组循环比较查找最大值
  55.             Next
  56.         Next
  57.     Next
  58.     MsgBox "数组循环比较 耗时:" & vbCr & Format(Timer - tms, "0.000s ") & k
  59.    
  60.    
  61. End Sub
复制代码

测试时,可以按以下组合:
1. m=10000: n=1     即1万行1列时: 速度比较循环次数 nn=100
2. m=10000: n=10   即1万行10列时: 速度比较循环次数 nn=10
3. m=10000: n=100 即1万行100列时: 速度比较循环次数 nn=1

结果都是: 工作表Max函数求Range区域对象的最大值时,速度比VBA内存数组的For……Next遍历比较还要快!

而且,已经dim arr()为长整型,更加方便VBA中数组的运算效率了。


TA的精华主题

TA的得分主题

发表于 2013-4-6 17:13 | 显示全部楼层
但是,如果是用 Application.max(arr)的方式进行,确实是速度更慢,远远不如VBA内存数组直接进行比较了。

因此结论是:
1. 如果数据仅仅是存在于VBA过程中的内存数组中,没有也不需要写入工作表单元格中去时,应该用VBA内存数组直接循环比较求最大值。

2. 如果数据已经存在于工作表单元格区域中,则不必读入数组而直接用Application.max([Range])的方法求最大值更快。

TA的精华主题

TA的得分主题

发表于 2013-4-6 17:13 | 显示全部楼层
本帖最后由 liucqa 于 2013-4-6 17:15 编辑
香川群子 发表于 2013-4-6 16:52
呵呵,如果是用工作表函数Max求VBA内存数组的最大值,
速度显然没有VBA内存数组直接For……Next循环快 ...

office本身是C/C++写的,使用的是C API,速度自然比VBA快多了,不是有人说C的速度比VB快10倍比VBA快100倍嘛。

谁要是没事可以用C++自己写代码,搞个XLL,看看计算最大值的速度。另外,算法用分而治之算法也许比较快,具体可以百度
您需要登录后才可以回帖 登录 | 免费注册

本版积分规则

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

GMT+8, 2024-5-20 20:32 , Processed in 0.032479 second(s), 8 queries , Gzip On, MemCache On.

Powered by Discuz! X3.4

© 1999-2023 Wooffice Inc.

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

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

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