前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Excel VBA解读(144): 使用Application事件和缓存将更快地获取已使用单元格区域

Excel VBA解读(144): 使用Application事件和缓存将更快地获取已使用单元格区域

作者头像
fanjy
发布2019-07-18 22:01:23
2.2K0
发布2019-07-18 22:01:23
举报
文章被收录于专栏:完美Excel完美Excel

学习Excel技术,关注微信公众号:

excelperfect

在上一篇文章中,建议加速检索已使用单元格区域最后一行方法之一是使用缓存和Application对象的AfterCalculate事件。

下面是演示代码:

'为缓存创建模块级数组

Dim UsedRows(1 To 1000, 1 To 2) AsVariant

Public Function GetUsedRows3(theRngAs Range)

'对于Excel 2007及以后的版本,存储并获取已使用的单元格行数

Dim strBookSheet As String

Dim j As Long

Dim nFilled As Long

Dim nRows As Long

'为此工作簿和工作表创建标签

strBookSheet = Application.Caller.Parent.Parent.Name & "_"& _

Application.Caller.Parent.Name

If Val(Application.Version) >= 12 Then

'查看缓存

For j = LBound(UsedRows) ToUBound(UsedRows)

If Len(UsedRows(j, 1)) > 0 Then

nFilled = nFilled + 1

If UsedRows(j, 1) =strBookSheet Then

'找到了

GetUsedRows3 = UsedRows(j,2)

Exit Function

End If

Else

'如果第一行是空行则退出循环

Exit For

End If

Next j

End If

'找到已使用的行数

nRows = theRng.Parent.UsedRange.Rows.Count

If Val(Application.Version) >= 12 Then

'在缓存中存储

nFilled = nFilled + 1

If nFilled <= UBound(UsedRows) Then

UsedRows(nFilled, 1) = strBookSheet

UsedRows(nFilled, 2) = nRows

End If

End If

GetUsedRows3 = nRows

End Function

Sub ClearCache()

'清空已使用单元格区域缓存的第一行

UsedRows(1, 1) = ""

End Sub

注意,在此代码中包含错误处理语句!

首先声明一个包含1000行和2列的模块级别数组(UsedRows)。每行将在第1列(工作簿名称和工作表名称)中保存一个键,并在第2列中保存该工作簿中该工作表已使用单元格区域中的行数。假设只缓存包含这些用户自定义函数的前1000个工作表!

键或标签是通过将调用单元格的父级名称(即工作表)与调用单元格的父级名称的父级名称(包含该工作表的工作簿)连接而创建的。

然后循环该UsedRows数组查找键,但在第一个空行时退出循环。

如果找到键,则从第2列检索已使用单元格区域内的行数,将其作为函数的结果返回并退出该函数。

否则,查找已使用单元格区域中的行数,将其存储在UsedRange高速缓存的下一行中,并将其作为函数的结果返回。

该函数仅可在Excel 2007及更高版本中操作缓存。有两个原因:

1.Excel 2003及更早版本最多有65536行,因此无论如何找到已使用单元格区域相对较快。

2.只有Excel 2007及更高版本有AfterCalculate事件,该事件将在每次计算后用于清空缓存。

需要在每次计算后清空缓存,因为用户可能会改变已使用的单元格区域,因此安全的做法是在每次计算时重新创建缓存。AfterCalculate是一个应用程序级事件,在完成计算和相关查询和刷新后触发。(BeforeCalculate事件会更有用,但不存在!)

使用Application对象的AfterCalculate事件

首先,我添加了一个名为AppEvents的类模块,代码如下:

Private WithEvents App As Application

Private Sub Class_Initialize()

Set App = Application

End Sub

Private Sub App_AfterCalculate()

ClearCache

End Sub

在ThisWorkbook模块中添加代码:

Private XLAppEvents As AppEvents

Private Sub Workbook_Open()

Set XLAppEvents = New AppEvents

End Sub

这将设置应用程序级事件所需的挂钩。这么多的代码只是为了在每次计算后运行ClearCache过程!ClearCache只清空缓存中的第一个键,以便GetUsedRows3中的查找循环立即退出。

注意,Excel 2003及更早版本会忽略此代码:由于AfterCalculate事件不存在,因此它永远不会被调用,但仍然可以通过编译。

GetUsedRows3的执行效率

对于640K行数据,对GetUsedRows3的1000次调用只需要66毫秒,而上一篇文章中原始的CountUsedRows函数要花33秒。快500倍!

本文参与?腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-05-18,如有侵权请联系?cloudcommunity@tencent.com 删除

本文分享自 完美Excel 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与?腾讯云自媒体分享计划? ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
http://www.vxiaotou.com