首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >手动调用('=')或通过宏调用函数性能的差异

手动调用('=')或通过宏调用函数性能的差异
EN

Stack Overflow用户
提问于 2017-07-05 16:35:48
回答 3查看 1.4K关注 0票数 1

我写了一个查找函数。它的性能与有很大的不同,这取决于我是在工作表本身(通过'=')还是通过手动调用它。

我的宏执行以下操作:

代码语言:javascript
复制
Function betterSearch(searchCell As Range, aCol As Range, bCol As Range)
    For Each cell In aCol
        If LCase(cell.Value) = LCase(searchCell.Value) Then
            betterSearch = bCol.Cells(cell.row, 1)
            Exit For
        End If
        betterSearch = "Not found"
    Next
End Function

该宏打开resultsWorkbook和dataWorkbook,然后从dataWorkbook的resultWorkbook中搜索列A中的四个值,并从dataWorkbook的其他一些列返回相应的数据。

代码语言:javascript
复制
'...opening resultWorkbook and dataWorkbook
For aRow = 6 To 9
    resultWorkbook.Worksheets("B3").Cells(aRow, 125).Value = _
            betterSearch(resultWorkbook.Worksheets("B3").Cells(aRow, 1) _
            , dataWorkbook.Worksheets("page 1").Range("A:A") _
            , dataWorkbook.Worksheets("page 1").Range("Z:Z"))

         resultWorkbook.Worksheets("B3").Cells(aRow, 126).Value = _
            betterSearch(resultWorkbook.Worksheets("B3").Cells(aRow, 1) _
            , dataWorkbook.Worksheets("page 1").Range("A:A") _
            , dataWorkbook.Worksheets("page 1").Range("I:I"))
Next aRow

它真的很慢--一个文件需要分钟的。但当我手动打开该文件并键入公式并按Enter键时,它会立即计算(所以在这方面,我的函数不需要优化-它已经计算了fast,但只在工作表中,而不是在宏中)。

我不是在寻找来优化函数。我想要理解为什么会出现这样的性能差异,。我为运行的主应用程序和隐形应用程序都使用了Application.Calculation = xlCalculationManualExcelApp.Calculation = xlCalculationManual,它似乎将工作簿的状态更改为手动,但性能很慢,就好像工作簿仍然是自动的一样。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2017-07-05 17:29:17

可能与使用整个列范围有关。

我认为,当从宏调用函数时,您强制Excel为每个完整的列引用向VBA传输一百万个值(从Excel向VBA传输数据的速度非常慢)。

当从工作表中调用函数时,您只是传输一个range对象,然后逐个单元格循环,因此传输到VBA的数据量可能要少几十万倍(这取决于要查找匹配项所需的范围)。

尝试在宏中为完整的列引用设置范围变量,然后将范围变量而不是范围(i:i)传递给BetterSearch

票数 1
EN

Stack Overflow用户

发布于 2017-07-05 16:54:06

您可以使用Find函数,并使用MatchCase:=False,这样它将不区分大小写。

这将比循环遍历您的列快得多。

代码

代码语言:javascript
复制
Function betterSearch(searchCell As Range, aCol As Range, bCol As Range) As String

    Dim FndRng  As Range

    Set FndRng = aCol.Find(what:=LCase(searchCell.Value), LookIn:=xlValues, lookat:=xlWhole, _
                            searchorder:=xlRows, searchdirection:=xlNext, MatchCase:=False)
    If Not FndRng Is Nothing Then ' Find was successful
        betterSearch = bCol.Cells(FndRng.Row, 1)
    Else
        betterSearch = "Not found"
    End If

End Function
票数 1
EN

Stack Overflow用户

发布于 2019-01-18 04:55:21

原因是,因为您循环遍历宏中某个范围的单元格。与数组相比,这是非常慢的。每个cell.value调用都在减慢。在Excel本身中,这种减慢并不是因为Range对象是应用程序本身的对象。

一次将所有需要的数据从应用程序传递到VBA要比多次只传递少量数据要慢。

如果你重写了少量的代码,它将很快依赖于你调用它的位置。

首先将searchValue存储在一个变量中。因此,您不需要在每次调用时都计算公式。在您的代码中,每次比较都会计算搜索值,但这没有任何意义,因为它不会改变。

第二,将aCol范围的值存储在一个变量数组中。对于整个列,只需非常快地完成一次。之后,您可以非常快速地比较列中的每个值(比查找或匹配函数Performance comparison of Find / Match / Variant-Array更快)

以下是您更改后的代码

代码语言:javascript
复制
Function betterSearch(searchCell As Range, aCol As Range, bCol As Range)
    Dim searchVal as String
    Dim colVals() as Variant
    Dim r as Long
    searchVal = LCase(searchCell.Value)
    colVals = aCol.Value    ' Read data of whole column only once
    For r = 1 to Ubound(colVals,1)
        If LCase(colVals(r,1)) = searchVal Then
                betterSearch = bCol.Cells(r, 1)
                Exit For
        End If
        betterSearch = "Not found"
    Next 
End Function
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/44920998

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档