百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术文章 > 正文

[干货分享]VBA代码优化常用技巧(vba提升代码运行速度)

zhezhongyun 2025-06-12 19:04 4 浏览

天下武功,唯快不破


在这个时间就是金钱、效率就是生命的年代,浪费时间就是罪恶,尤其是对于程序猿来说,如果自己开发的程序,虽然功能实现了,但是在执行上还存在卡、慢的现象,那么不失为一件颇让人沮丧的事情。

大家都知道在Office里面可以用VBA进行二次开发,为日常工作提供了一条快捷的途径,善用它,可以大大的改善我们的工作体验和质量。今天跟大家分享的不是VBA本身,而是一些VBA代码常用的优化技巧,大神请绕路(也欢迎指点),VBA初学者或者爱好者可以看看,哪怕是得到一点点启发和借鉴,那也是极好的。

1.尽量调用内置功能,即,使用系统提供的属性、方法和函数

很多时候我们要实现某些功能,如果本身对excel不熟悉的话,可能会想办法去实现某些看上去很复杂的功能,殊不知,其实excel本身已经提供了类似的功能,有的时候可能仅仅是一个函数就解决了的事情,结果你搞半天,说不定辛苦弄出来,结果效率和效果还没内置的好。

在很大程度上,这简直是一定的,试想,你用的微软的软件,你编出来的东西能比别人开发人员还NB(不乏天才,所以我有所保留)?所以碰到这种情况还是省省心吧,能调用内置的尽量调用内置。

也有例外,如:

sub 获取数组最大值() 'VBA法

dim arr(),temp as byte,i,j,tim as long

for j=1 to 100000 '循环100000次,从而可以更好的进行时间比较

arr=array(1,7,8,6,9,3,5,7,6,8,9,4,1,2,4) '数组的值

temp=arra(1) '将数组中的第一个值赋予变量temp 'temp=worksheetfunction.max(arr) 调用max函数,效率反而偏低

for i=1 to UBound(arr) '循环比较数组中所有元素

if arra(i)>temp then temp=arr(i) '如果数组中某元素大于变量,即将该值赋予变量temp

next i

next j

end sub

先前在帮助一些学生朋友解决VBA难题的时候,碰到过别人计算机老师出题,为了偷懒,直接挑几个工作表函数,让学生拿代码给编出来,这是典型的放着内置的不用而自己编的案例,当然老师的出发点可能是训练学生的逻辑思维和算法理解能力。

2.尽量减少使用对象引用

  • 在循环中尽量减少对对象的引用,多用with... end with语句,圆点越少越省时

  • 用set语句将反复引用的对象设置为对象变量,因为变量存在内存中

  • 利用对象循环代替单元格循环,如判断单元格批注,可以循环批注comments对象,直接找到每个批注,再利用parent获取该批注的父对象单元格即可。

  1. sub批注循环()

  2. dim com as comment,address asstring

  3. for each com in activeSheet.comments

  4. address=address&com.parent.address(0,0)&chr(10)

  5. next

  6. msgbox address

  7. endsub

  8. sub 单元格循环()

  9. dim rng as range,address as string,bl as boolean

  10. on error resume next

  11. for each rng in activesheet.usedrange

  12. bl=rng.comment.visible

  13. if err=0 then address=address&rng.address(0,0)&chr(10)

  14. err.clear:

  15. next rng

  16. msgbox address

  17. end sub

3.减少对象的激活和选择

  • 少用select和activate语句

这个通常会出现在我们自己录制宏代码的时候,excel记录了大量的点击和激活动作,而这些都不是必须的,大多数都可以省略掉(有些操作必须用到激活或者选择的除外)

4.关闭屏幕更新

就是程序运行的时候会看到屏幕在闪烁,这个会影响计算机的性能,也会闪瞎眼,所以基本上编程的人都会默认使用这一条(尤其是对于运行时间比较长的,短的可以视情况不加)


Application.ScreenUpdating=False '通常放在循环语句前
...Application.ScreenUpdating=True

5.变量的使用

  • 强制变量声明(OptionExplicit):在设置里面勾选,会节省时间,自动带出,而不是自己手动敲出来的

  • 尽量显式声明变量:事前连接--early binding;定义object类型的属于事后连接,late binding。通常事前定义会节省时间,但往往会有兼容性问题,后定义的适配性比较好

  • 选择合适的变量类型:缺省会默认Variant型,但是会增加内存耗用,能明确的就具体指明

  • 善用变量:对于反复出现的数值或者字符串,尽量声明一个常量来取代该值,直接调用,修改的时候也能做到一改都改,而不用改动多个地方

讲到这里,想强调一下,有时候为了效率,有的人喜欢在代码编写的时候采用一些简写或者隐式声明,这个确实会让我们少敲不少字,但是带来的另外一个问题是,一旦代码出现了问题,调试或者找错误的时候就会很抓狂了,可能从整体的时间效率上反而不划算,所以还是建议大家养成良好的编程习惯,变量都写清楚,勤备注,这样易读性和可维护性好

6.善用带$的字符串处理函数

VBA中有2套字符串处理函数,带$和不带$的。

如果不带$的的函数处理字符串,则VBA将字符串作为variant数据计算,用带$的,则当string处理。而前者需要耗费更多的内存

7.善用循环中的步长减少循环次数

如判断奇偶,有了步长,就可以省去判断语句,加快速度

讲到循环,还有一个类似的例子:

就是我们在遍历某个区域的时候,如果能用目标区域(Target)与已用区域(UsedRange)的交集(Intersect)区域来循环的话,会缩小循环的范围,规避掉一些空的单元格的比对

8.利用数组代替单元格对象

将中间过程存在数组中,直接从内存调用,最后再读取

这个应该是应用的最多的,效果是最明显的,少了单元格的交互,会省不少事。

当然字典作为特殊的数组存在形式,一样的也能来做这个事情

实例:

对几千个个学生中不及格的成绩标示“不及格”

sub 对小于60分成绩进行注释()

Dim i as integer,tim as long,arr1(),arr2()'将成绩赋予数组变量arr1=range([b2],cells(rows.count,2).end(xlup))

'重置第二个数组变量大小

ReDim arr2(1 to UBound(arr1),1 to 1)

'循环数组for i=1 to UBound(arr1)

if arr1(i,1)<60 then arr2(i,1)="不及格"

next i

'将第二个数组的值赋予单元格

range([c2],cells(rows.count,2).end(xlup).offset(0,1))=arr2

end sub

9.重复调用UDF时才使用它

有点绕啊,UDF,即user-defined-function,即用户自定义函数

为了程序运行的高效,我们通常会把长代码拆成几个子代码或者自定义函数,来相互调用。达到方便调试和互相引用的目的。UDF适合多次调用时,否则调用的速度甚至比执行的速度更慢。

比较短小的和仅使用一次的function,建议直接内置在sub代码中而不是调用UDF。

10.将不改变值或者属性的语句放到循环语句外

这一点往往会被人忽略,可能循环的重要语句本身就一两句,其他无关语句很多的话,在循环的时候会反复check,这个过程会耗时

11.利用长度计算判断单元格是否为空

第一次看到罗刚军老师用这个的时候百思不得姐,上论坛问了很多人也不知道。后来在实践中,逐渐发现这个效率更高(很隐晦,比较难得找合适的例子,老师能发现这个确实是下了功夫的),而且在很多时候用len方法还能解决别的一些比较棘手的问题,比如判断非空单元格的时候或者某些对象的时候,我们有时候搞不清楚返回的值的属性,

xx=""

xx is empty

xx is nothing

都不如一句len(xx)=0来得简便

range("a1")="" '建议len法,此法效率更高len(range("a1"))=0 '.value省略,range的默认属性

好了说了这么多,想必大家都跃跃欲试了,那么怎么知道自己优化结果是积极的呢?我们可以测试啊,下面附上测试代码:

程序运行时间测试代码:

sub aaa()

dim tim as long

tim=timer '获取当前时间

for ...

next

msgbox format(timer-tim,"0.00")&"秒" '执行报告时间

end sub

通常有2种方法timer函数和time函数,网上很多人问有啥区别,搞不清楚,这里简单解释一下(理解有误的话,望高手不吝赐教):

  1. 时间很短时,可以用timer函数,返回秒,即相对于当天相对午夜0点时候经过了多少秒(感觉时间长了,统计不是蛮准,自己编程体会)

  2. 时间比较长时,可以用time,time是按照时间如22:58:30这样记录的,即运行前后电脑时间相减

更多精彩,敬请关注微信号Excel-365,后续有更新,会及时分享!

相关推荐

JavaScript做个贪吃蛇小游戏(过关-加速),无需网络直接玩。

JavaScript做个贪吃蛇小游戏(过关-则加速)在浏览器打开文件,无需网络直接玩。<!DOCTYPEhtml><htmllang="en"><...

大模型部署加速方法简单总结(大模型 ai)

以下对大模型部署、压缩、加速的方法做一个简单总结,为后续需要备查。llama.cppGithub:https://github.com/ggerganov/llama.cppLLaMA.cpp项...

安徽医大第一医院应用VitaFlow Liberty(R)Flex为患者焕然一“心”

近日,在安徽医科大学第一附属医院心血管内科负责人暨北京安贞医院安徽医院业务副院长喻荣辉教授的鼎力支持和卓越带领下,凭借着先进的VitaFlowLiberty(R)Flex经导管主动脉瓣可回收可...

300 多行代码搞定微信 8.0 的「炸」「裂」特效!

微信8.0更新的一大特色就是支持动画表情,如果发送的消息只有一个内置的表情图标,这个表情会有一段简单的动画,一些特殊的表情还有全屏特效,例如烟花表情有全屏放烟花的特效,炸弹表情有爆炸动画并且消息和...

让div填充屏幕剩余高度的方法(div填充20px)

技术背景在前端开发中,经常会遇到需要让某个div元素填充屏幕剩余高度的需求,比如创建具有固定头部和底部,中间内容区域自适应填充剩余空间的布局。随着CSS技术的发展,有多种方法可以实现这一需求。实现步骤...

css之div内容居中(css中div怎么居中)

div中的内容居中显示,包括水平和垂直2个方向。<html><head><styletype="text/css">...

使用uniapp开发小程序遇到的一些问题及解决方法

1、swiper组件自定义知识点swiper组件的指示点默认是圆圈,想要自己设置指示点,需要获得当前索引,然后赋给当前索引不同的样式,然后在做个动画就可以了。*关键点用change方法,然后通过e.d...

微信小程序主页面排版(怎样设置小程序的排版)

开发小程序的话首先要了解里面的每个文件的作用小程序没有DOM对象,一切基于组件化小程序的四个重要的文件*.js*.wxml--->view结构---->html*.wxss--...

Vue动态组件的实践与原理探究(vue动态组件component原理)

我司有一个工作台搭建产品,允许通过拖拽小部件的方式来搭建一个工作台页面,平台内置了一些常用小部件,另外也允许自行开发小部件上传使用,本文会从实践的角度来介绍其实现原理。ps.本文项目使用VueCLI...

【HarmonyOS Next之旅】兼容JS的类Web开发(四) -> tabs

目录1->创建Tabs2->设置Tabs方向3->设置样式4->显示页签索引5->场景示例编辑1->创建Tabs在pages/index目录...

CSS:前端必会的flex布局,我把布局代码全部展示出来了

进入我的主页,查看更多CSS的分享!首先呢,先去看文档,了解flex是什么,这里不做赘述。当然,可以看下面的代码示例,辅助你理解。一、row将子元素在水平方向进行布局:1.垂直方向靠顶部,水平方向靠...

【HarmonyOS Next之旅】兼容JS的类Web开发(四) -> swiper

目录1->创建Swiper组件2->添加属性3->设置样式4->绑定事件5->场景示例编辑1->创建Swiper组件在pages/index...

CSS:Flex布局,网页排版神器!(css3 flex布局)

还在为网页排版抓狂?别担心,CSS的flex布局来了,让你轻松玩转各种页面布局,实现网页设计自由!什么是Flex布局?Flex布局,也称为弹性布局,是CSS中的一种强大布局方式,它能够让你...

移动WEB开发之flex布局,附携程网首页案例制作

一、flex布局体验传统布局兼容性好布局繁琐局限性,不能再移动端很好的布局1.1flex弹性布局:操作方便,布局极为简单,移动端应用很广泛PC端浏览器支持情况较差IE11或更低版本,不支持或仅部...

2024最新升级–前端内功修炼 5大主流布局系统进阶(mk分享)

2024最新升级–前端内功修炼5大主流布局系统进阶(mk分享)获课》789it.top/14658/前端布局是网页设计中至关重要的一环,它决定了网页的结构和元素的排列方式。随着前端技术的不断发展,现...