#excel #vba #performance
#excel #vba #Производительность
Вопрос:
Я создал функцию поиска, которая находит результат на отдельной вкладке на том же листе с 4 разными полями для сопоставления.
При запуске это занимает слишком много времени (до такой степени, что мне приходится прерывать выполнение макроса). Мне нужно создать одну и ту же функцию поиска для 8 разных полей на основе одних и тех же критериев соответствия. Любые советы о том, как ускорить этот запрос или построить его более динамичным способом, чтобы я мог просматривать все 8 столбцов одновременно, а не создавать функции и вспомогательные элементы для каждого поля поиска?
Function fcst_bal_find(ByVal Anode As String, ByVal LoB As String, ByVal Month As String, ByVal Year As String) As Variant
Dim Fcst_Essbase As Worksheet
Dim fcst_rowcnt
Dim act_rowcnt
fcst_rowcnt = Sheets("Date Dims").Range("B7")
act_rowcnt = Sheets("Date Dims").Range("B8")
Set Fcst_Essbase = Sheets("Fcst Essbase Pull")
For i = 2 To fcst_rowcnt 4
If WorksheetFunction.Trim(Fcst_Essbase.Cells(i, 1).Value) = Anode Then
If WorksheetFunction.Trim(Fcst_Essbase.Cells(i, 2).Value) = LoB Then
If WorksheetFunction.Trim(Fcst_Essbase.Cells(i, 3).Value) = Month Then
If "Y" amp; Right(WorksheetFunction.Trim(Fcst_Essbase.Cells(i, 4).Value), 2) = Year Then
fcst_bal_find = Fcst_Essbase.Cells(i, 5).Value
Exit Function
End If
End If
End If
End If
Next i
fcst_bal_find = "N/A"
End Function
Sub balfcst_find()
Dim fcst_tab As Worksheet
Dim match As Variant
Dim Anode As String
Dim LoB As String
Dim Month As String
Dim Year As String
Dim fcst_rowcnt
Dim act_rowcnt
fcst_rowcnt = Sheets("Date Dims").Range("B7")
act_rowcnt = Sheets("Date Dims").Range("B8")
Set fcst_tab = Sheets("Cartesian Product - Fcst")
For i = 2 To fcst_rowcnt
Anode = fcst_tab.Range("A" amp; i).Value
LoB = fcst_tab.Range("B" amp; i).Value
Month = fcst_tab.Range("C" amp; i).Value
Year = fcst_tab.Range("D" amp; i).Value
match = fcst_bal_find(Anode, LoB, Month, Year)
fcst_tab.Cells(i, 5) = match ' test the output
Next i
End Sub
Комментарии:
1. Используйте альтернативный массив — считайте рассматриваемый диапазон в массив и зацикливайте массив вместо зацикливания ячеек, как вы делаете сейчас.
2. ОК. Быстрее всего для поиска данных используется автофильтр, за которым следуют словари. Также вы пробовали yes bigbens comment — перебирать массив в противоположность ячейкам. это тоже было бы быстрее.
3. По моему опыту, «АвтоФильтр` не является быстрым @DavidWooley-AST. Это медленно и может даже давать ошибки. Вариант массива — это путь.
4. ОК. Я согласен . Я шел по временам некоторых VBA YouTubers , ирландца. «Освоение макросов Excel» . Зависит от того, какой процесс и для какой цели. Но мне всегда нравится бросать вызов самому себе..
5. @ David Wooley — AST: Вы, вероятно, имели в виду расширенный фильтр , и вы говорите о Поле Келли из Excel Macro Mastery .
Ответ №1:
Вот пример использования variant array для сопоставления чего-либо из моего текущего проекта. Вы можете изменить в соответствии с вашими потребностями.
Private Function verifyMod(modValue As Double, state As String) As Boolean
If Len(modValue) Then
Dim modTable As ListObject
Set modTable = lookupsAUState.ListObjects("stateWritingCoModMinMax")
Dim v As Variant
v = modTable.DataBodyRange.value
Dim company As String
company = StrConv(xmlCo.Range("insuranceCompanyName"), vbProperCase)
Dim x As Long
For x = LBound(v) To UBound(v)
If v(x, modTable.ListColumns("Company").index) = company Then
If v(x, modTable.ListColumns("State").index) = state Then
If modValue >= v(x, modTable.ListColumns("Min").index) And modValue <= v(x, modTable.ListColumns("Max").index) Then
verifyMod = True
Else
MsgBox state amp; " allows for modifications between " amp; v(x, modTable.ListColumns("Min").index) amp; " and " amp; v(x, modTable.ListColumns("Max").index) amp; ". Please enter a modification within that range."
End If
Exit For
End If
End If
Next
End If
End Function