【发布时间】:2021-04-21 15:08:49
【问题描述】:
我正在通过 Excel 表 (Listobject) 运行 VBA for each 循环,该表根据给定路径检查文件是否存在。我的表已经扩展,并且有 68K 列表行。启动代码后很快报错Run-time-error '7': Out of memory
它运行良好,有 63K 行(在 5 分钟内完成),根据谷歌搜索,似乎有一种叫做“64K 段边界”的东西。这是什么影响了我的代码运行,因为它真的感觉它首先缓冲了行数,然后在没有开始实际运行任何东西的情况下反弹回来。是否有一个简单的解决方法,无需将我的数据集分成多个批次?坦率地说,我很惊讶 64K 限制在 2021 年仍然存在于 Excel 中。
在 64 位 Excel 2019 上运行它,但在 Office365 上也没有运气。
Sub CheckFiles()
Dim Headers As ListObject
Dim lstrw As ListRow
Dim strFileName As String
Dim strFileExists As String
Application.ScreenUpdating = False
Set ws = ThisWorkbook.Sheets("Import")
Set Headers = ws.ListObjects("Import")
For Each lstrw In Headers.ListRows
strFileName = lstrw.Range(7)
strFileExists = Dir(strFileName)
If strFileExists = "" Then
lstrw.Range(4) = "not found"
Else
lstrw.Range(4) = "exists"
End If
Next lstrw
Set ws = Nothing
Set Headers = Nothing
Application.ScreenUpdating = True
End Sub
【问题讨论】:
-
将所需数据读入数组,用循环处理数组,然后将数组连同结果一起写回单元格。使用数组时,这应该运行得快得多。每个读写操作都会带来很多开销。如果您使用数组,则开始时只有一个读取操作,最后只有一个写入操作。而不是循环中每次迭代的其中一个。
-
如果您使用常规范围而不是列表对象,您会看到同样的情况吗?
-
刚刚做了一个测试:可以确认行为。更改为常规的
for-loop (for i=1 to list.ListRows.Count) 没有任何问题,在 3 秒内迭代超过 70k 行。 -
@FunThomas 现在这很有趣,因为通常
For Each...Next在对象集合上比For...Next循环快数量级。 ExcelListObjectAPI 中是否存在内存泄漏错误? -
For Each...Next使用一种枚举器机制,一次生成一个对象...看起来像ListRows集合中的一个实现错误。