Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/excel/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Excel 手动调用(';=';)或通过宏调用之间的函数性能差异_Excel_Vba_Performance_Excel Formula - Fatal编程技术网

Excel 手动调用(';=';)或通过宏调用之间的函数性能差异

Excel 手动调用(';=';)或通过宏调用之间的函数性能差异,excel,vba,performance,excel-formula,Excel,Vba,Performance,Excel Formula,我写了一个查找函数。它的性能差别很大,这取决于我是在工作表上手动调用它(通过“=”)还是通过宏调用它 我的宏执行以下操作: 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 = bC

我写了一个查找函数。它的性能差别很大,这取决于我是在工作表上手动调用它(通过“=”)还是通过宏调用它

我的宏执行以下操作:

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中的resultsWorkbook搜索a列中的四个值,并从dataWorkbook的其他列返回相应的数据

'...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键时,它会立即计算(因此,在这方面,我的函数不需要优化-它已经计算快速,但只是在工作表中,而不是在宏中)


我不想优化功能。我想了解性能差异产生的原因。我有
Application.Calculation=xlCalculationManual
用于运行的主应用程序和执行所有工作的不可见应用程序:
ExcelApp.Calculation=xlCalculationManual
,它似乎正在将工作簿的状态更改为手动,但性能很慢,就好像工作簿仍然存在一样自动。

您可以使用
Find
功能,并使用
MatchCase:=False
使其不区分大小写

它将比在你的专栏中循环快得多

代码

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

可能与使用整个列范围有关
我认为,从宏调用函数时,强制Excel为每个整列引用将一百万个值传输到VBA(将数据从Excel传输到VBA非常慢)
从工作表调用函数时,您只传输一个范围对象,然后逐单元格循环,因此传输到VBA的数据量可能会减少数十万倍(取决于查找匹配项所需的距离)


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

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

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

如果你重写你的代码,它将是快速独立的从哪里你调用它

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

其次,将aCol范围的值存储在变量数组中。这是一次非常快的整个列。之后,您可以非常快速地比较列中的每个值(比查找或匹配函数快)

这是您更改的代码

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

使用
worksheetfunction.match
除了问题之外-是否有理由需要在VBA中使用此(嗯)
BetterSearch
函数?您基本上编写了一个性能较差的基本Vlookup或Index/Match版本。@Rik Sportel,我需要它,因为Vlookup接收和查找的符号数量最多,而我的函数没有这个缺陷。我在问题中说,当我自己称之为betterSearch时,它执行得很快!真正的问题是为什么它在宏中变慢。只检查打开工作簿所需的时间。@UGP,它相对较小。我有一个GUI,它告诉我当每个操作开始时,查找值会占用大部分时间。谢谢您的回复。但我仍然想知道为什么同一个函数的结果不同,问题是关于这一点,而不是优化函数。我决定按照您的建议优化我的函数,但不幸的是,您的代码在
Set FndRng…
行上出现了
类型不匹配
错误…谢谢。旅游回答真的很有帮助。我创建了
Range
变量,并将
Range(“I:I”)
替换为
Range(“I2:I1200”)
。性能大大提高。然而,它仍然比手动重新计算每个值要慢得多。。。我想知道还有什么可以做的吗?它看起来相当可疑-当我只查找5-10个值时,速度会非常快,而增加查找值的数量似乎会成倍地增加所需的时间。