ExcelHome技术论坛

 找回密码
 免费注册

QQ登录

只需一步,快速开始

快捷登录

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

vba运行速度的提升

[复制链接]

TA的精华主题

TA的得分主题

发表于 2020-12-4 20:04 | 显示全部楼层 |阅读模式
[广告] Excel易用宝 - 提升Excel的操作效率 · Excel / WPS表格插件       ★免费下载 ★       ★ 使用帮助
1.火眼识破隐藏的Variant变量

如果没有用As语句声明变量,默认类型就是Variants,好比:

Dim name ' this is a variant

或者,当前模块下没有声明Option Explicit语句时,任何变量都是Variants类型

许多开发者,特别是那些先前是C程序员的人,城市深信下面的语句将声明2个Interger类型变量

Dim x, y As Integer

而实际上,x被声明为了variant类型.由于variant类型变量要比Integer类型慢很多,所以要特别注意这种情况.正确的一行声明体例是

Dim x As Integer, y As Integer

2.为常量界说合适的类型

VB在内部使用最简单、最可能的数据类型保存符号数值,这意味着最通常的数字类型-好比0或者1-都依照Integer类型存储.如果在浮点表达式中使用这些常量,可以通过常量的合适类型来加速程序运行,就象下面的代码:

value# = value# + 1#.

这个语句强迫编译器依照Double格式存储常量,这样就省却了运行时的隐含转换工作.还有另外的一种措置体例就是:在常量声明时就进行相应类型的界说,代码如下:

Const ONE As Double = 1

3.静态变量慢于动态变量

在过程中引用静态局部变量要比引用常规局部动态变量慢2-3倍.要想真正地加速过程的执行速度,最完全的体例就是将所有的静态变量转换为模块级别变量;

这种体例的唯一不足是:过程很少是自包含的,如果要在其他工程中重用,就必须同时拷贝并粘贴这些模块级别变量

另外的一种措置体例是:在时间要求高的循环前,将静态变量数值装入动态变量中

善用"Assume No Aliasing"(注:似乎是假定无别号)编译选项

据说,如果过程能够2次或屡次引用同样的内存地址,那么过程就会包含别号数值.一个典型的例子如下:
Dim g_GlobalVariable As Long... Sub ProcWithAliases(x As Long)x = x + 1 g_GlobalVariable = g_GlobalVariable + 1 End Sub

如果传递给这个过程g_GlobalVariable变量,则将通过一个直接引用以及x参数两种体例修改变量的数值2次. (注:这里可以理解,但历来没有写过类似这样的代码 :-D

别号数值经常是不良编程习惯的产品,对程序优化有害无益.事实上,如果能够完全确认应用程序历来没有使用到别号变量,就可以打开"Assume No Aliasing"高级编译选项,这将告知编译器没有过程可以修改同一内存地址,使编译器产生更加有效率的汇编代码.更特另外是,编译程序将试图缓冲这些数据到CPU的寄存器中,从而明显地加速了程序运行

总结一下,当遇到以下情况时,就不会有别号数值:

(1) 过程不引用任何全局变量 (2) 过程引用了全局变量,但历来欠亨过ByRef参数类型传递同一变量给过程 (3) 过程含有多个ByRef参数类型,但历来不传递同一变量到其中的2个或者多个之中.

4.拜候简单变量总是快于数组元素值

读写数组中的元素速度通常都慢于拜候一个简单变量,因此,如果在一个循环中要重复使用同一数组元素值,就应该分派数组元素值光临时变量中并使用这个变量.下面举一个例子,检测整数数组中是否存在重复项:
Function AnyDuplicates(intArray() As Integer) As Boolean '如果数组包含重复项,返回True Dim i As Long, j As Long, Dim lastItem As Long Dim value As Integer '只计算机UBound()一次 lastItem = UBound(intArray) For i = LBound(intArray) To lastItem ' 保存intArray(i)到非数组变量中 value = intArray(i) For j = i + 1 To lastItem If value = intArray(j) Then AnyDuplicates = True Exit Function End If Next Next '没有发现重复项 AnyDuplicates = False End Function

上述程序有2层循环,通过缓存intArray(i)的数值到一个普通的、非数组变量中,节省了CPU运行时间.经测试,这将提高80%的速度.

注:这其实是一种思想。我们在Excel VBA中如果,如果一段代码中需要屡次引用到一个对象的属性值(如cells(5,5),range.address等等),那么我们可以考虑在代码真正措置前先用一个临时变量将那个对象属性值保存起来,在代码中只对那个变量进行操作即可,最后如有需要再将变量写回到原对象。

5.快速清除数组部分内容

清除动态数组的最快体例是使用ReDim,清除静态数组则是使用删除.可是如果只想清除数组的一部分内容,怎么办呢?看上去似乎只能使用For-Next循环了;

如果措置的是数字数组,有一个较快的体例.它基于ZeroMemory API函数,正如函数名所示,它能将一块内存区域填充为0.看看怎么应用这个函数来清除一个Long类型数组的一部分内容:
Private Declare Sub ZeroMemory Lib "kernel32" Alias "RtlZeroMemory" (dest As Any, ByVal Bytes As Long)'界说数组,填充数据 Dim a(1000) As Long For i = 1 To UBound(a) a(i) = i Next '从a(200)开始清除100个元素内容 ZeroMemory a(200), 100 * Len(a(1))

vba代码运行速度慢的解决方法.zip

170.49 KB, 下载次数: 4

vba提速方法

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

本版积分规则

关闭

最新热点上一条 /1 下一条

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

GMT+8, 2024-4-26 01:22 , Processed in 0.033187 second(s), 12 queries , Gzip On, MemCache On.

Powered by Discuz! X3.4

© 1999-2023 Wooffice Inc.

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

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

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