【发布时间】:2020-02-26 18:58:29
【问题描述】:
我写了一个函数NA_2_X(Range, Variant)来接受一个数组,将所有#NA转换成一个Variant,并返回新的数组:
{=NA_2_X(A1:A3000, 0)}
这比编写费力的工作表函数要慢得多:
{=IF(ISNA(A1:A3000), 0, A1:A3000)}
300 次调用 NA_2_X() 大约需要 10 秒,而 IF() 语句几乎是即时的。最终我想做一些更复杂的事情,不能使用if() 语句。
Function NA_2_X(ByVal rng As Range, ByVal X As Variant) As Variant
Dim NoRows As Long, NoCols As Long
Dim r As Long, c As Long
Dim ret() As Variant
NoRows = rng.Rows.Count
NoCols = rng.Columns.Count
ReDim ret(1 To NoRows, 1 To NoCols)
For c = 1 To NoCols
For r = 1 To NoRows
If Application.IsNA(rng(r, c)) Then
ret(r, c) = X
Else
ret(r, c) = rng(r, c)
End If
Next r
Next c
NA_2_X = ret
Exit Function
End Function
循环本身看起来很快,只是循环中心的几行看起来很慢。如果我删除对IsNA() 的调用,它需要大约一半的时间,但仍然很慢。
【问题讨论】:
-
不太清楚你的意思(我不是 VBA 专家)。我确实尝试过 Dim tmp as Variant, tmp=rng(r,c) 然后引用 tmp 。它帮助了一点,但不是很多。
-
Dim tmp() as Variant,然后是tmp = rng.Value。然后循环遍历 temp(使用LBound和UBound来确定边界,而不是NoRows和NoCols。这会更快(虽然不能保证它会像普通函数一样快)。跨度> -
使用带有错误参数的
SpecialCells怎么样(虽然不能区分NA和其他)。 -
tmp.rng.Value 有帮助,它将每次调用的时间从 32ms 减少到 15ms,但不幸的是它仍然太慢了。看来 Application.IsNA(tmp(r,c)) 很慢,不知道为什么。
-
arr = .Evaluate("IF(ISNA(" & Rng.Address & ")," & X & "," & Rng.Address & ")")会给你一个值数组。我也不确定您到底想做什么,所以建议的行可能毫无意义
标签: arrays excel vba performance function