优化使用大型数组的Excel公式

优化使用大型数组的Excel公式,excel,excel-formula,excel-2010,Excel,Excel Formula,Excel 2010,我使用了下面提到的excel公式 =INDEX(TABL,SMALL(IF(COUNTIF(H2,$A$1:$A$325779)*COUNTIF(I2,"<="&$B$1:$B$325779),ROW(TABL)-MIN(ROW(TABL))+1),1),3) 这是你需要的吗 Sub subFindValue() 'Speed up Application.ScreenUpdating = False Application.DisplayStatusBa

我使用了下面提到的excel公式

=INDEX(TABL,SMALL(IF(COUNTIF(H2,$A$1:$A$325779)*COUNTIF(I2,"<="&$B$1:$B$325779),ROW(TABL)-MIN(ROW(TABL))+1),1),3)
这是你需要的吗

Sub subFindValue()
    'Speed up
    Application.ScreenUpdating = False
    Application.DisplayStatusBar = False
    Application.Calculation = xlCalculationManual
    Application.EnableEvents = False

    Dim strNamedValue As String: strNamedValue = Range("E3")
    Dim curHigherThanValue As Currency: curHigherThanValue = Range("F3")
    Dim varRow As Variant

    varRow = 1
    Do Until IsEmpty(Cells(varRow, 1))
        If Cells(varRow, 1) = strNamedValue And Cells(varRow, 2) > curHigherThanValue Then
            Range("G3") = Cells(varRow, 3)
            Exit Do
        End If
        varRow = varRow + 1
        Loop

    'Slow down
    Application.ScreenUpdating = True
    Application.DisplayStatusBar = True
    Application.Calculation = xlCalculationAutomatic
    Application.EnableEvents = True
    End Sub
这是你需要的吗

Sub subFindValue()
    'Speed up
    Application.ScreenUpdating = False
    Application.DisplayStatusBar = False
    Application.Calculation = xlCalculationManual
    Application.EnableEvents = False

    Dim strNamedValue As String: strNamedValue = Range("E3")
    Dim curHigherThanValue As Currency: curHigherThanValue = Range("F3")
    Dim varRow As Variant

    varRow = 1
    Do Until IsEmpty(Cells(varRow, 1))
        If Cells(varRow, 1) = strNamedValue And Cells(varRow, 2) > curHigherThanValue Then
            Range("G3") = Cells(varRow, 3)
            Exit Do
        End If
        varRow = varRow + 1
        Loop

    'Slow down
    Application.ScreenUpdating = True
    Application.DisplayStatusBar = True
    Application.Calculation = xlCalculationAutomatic
    Application.EnableEvents = True
    End Sub

如果您的数据在第1列的第2列进行排序,则SpeedTools Filter.Ifs函数将比您的公式快很多(至少快50倍)



免责声明:我是商业Excel加载项产品SpeedTools的作者
您可以从以下位置下载完整的试用版:

如果您的数据在第1列的第2列进行排序,则SpeedTools筛选器。Ifs函数将比您的公式快很多(至少快50倍)



免责声明:我是商业Excel加载项产品SpeedTools的作者
您可以从以下位置下载完整的试用版:

这应该有效,并且比任何需要循环每行的VBA解决方案快得多,只要您可以将B列中的日期按降序排序:

以数组形式输入以下公式(使用Ctrl+Shift+Enter代替Enter

=INDEX($C$1:$C$15,MATCH(G2,IF($A$1:$A$15=F2,$B$1:$B$15),-1))
你应该以这样的方式结束:

说明:

IF($A$1:$A$15=F2,$B$1:$B$15)
正在构建一个值数组,该数组等于测试字位于同一行A列的B列中的行

MATCH(G2,IF($A$1:$A$15=F2,$B$1:$B$15),-1)
这是使用从Id语句构建的数组来从测试数据中查找大于或等于查找值的最小值

=INDEX($C$1:$C$15,MATCH(G2,IF($A$1:$A$15=F2,$B$1:$B$15),-1))
一旦所有这些都在一起,“索引”将返回C列中与匹配值位于同一位置的值

更新:如果您正在查找tigeravatar的答案返回的内容,那么下面是另一个将返回所有值的VBA函数:

Sub GetValues()

With Application
    .ScreenUpdating = False
    .EnableEvents = False
    .Calculation = xlCalculationManual
End With

Dim strMetalName As String: strMetalName = [E3]
Dim dbMinimumValue As Double: dbMinimumValue = [F3]

Range("G3:G" & Rows.Count).ClearContents

With Range("TABL")
    .AutoFilter Field:=1, Criteria1:=strMetalName
    .AutoFilter Field:=2, Criteria1:=">=" & dbMinimumValue, Operator:=xlAnd
     Range("C2", [C2].End(xlDown)).Copy [G3]
    .AutoFilter
End With

With Application
    .ScreenUpdating = True
    .EnableEvents = True
    .Calculation = xlCalculationAutomatic
End With
End Sub

对我来说,运行his需要5-7分钟,而这需要1.5秒,其中我的第一个答案返回包含最接近匹配结果的一行,该sub将返回大于或等于的所有值。

这应该有效,并且比任何VBA解决方案快得多,只要您可以对日期进行排序,该解决方案就需要循环每行B列降序:

以数组形式输入以下公式(使用Ctrl+Shift+Enter代替Enter

=INDEX($C$1:$C$15,MATCH(G2,IF($A$1:$A$15=F2,$B$1:$B$15),-1))
你应该以这样的方式结束:

说明:

IF($A$1:$A$15=F2,$B$1:$B$15)
正在构建一个值数组,该数组等于测试字位于同一行A列的B列中的行

MATCH(G2,IF($A$1:$A$15=F2,$B$1:$B$15),-1)
这是使用从Id语句构建的数组来从测试数据中查找大于或等于查找值的最小值

=INDEX($C$1:$C$15,MATCH(G2,IF($A$1:$A$15=F2,$B$1:$B$15),-1))
一旦所有这些都在一起,“索引”将返回C列中与匹配值位于同一位置的值

更新:如果您正在查找tigeravatar的答案返回的内容,那么下面是另一个将返回所有值的VBA函数:

Sub GetValues()

With Application
    .ScreenUpdating = False
    .EnableEvents = False
    .Calculation = xlCalculationManual
End With

Dim strMetalName As String: strMetalName = [E3]
Dim dbMinimumValue As Double: dbMinimumValue = [F3]

Range("G3:G" & Rows.Count).ClearContents

With Range("TABL")
    .AutoFilter Field:=1, Criteria1:=strMetalName
    .AutoFilter Field:=2, Criteria1:=">=" & dbMinimumValue, Operator:=xlAnd
     Range("C2", [C2].End(xlDown)).Copy [G3]
    .AutoFilter
End With

With Application
    .ScreenUpdating = True
    .EnableEvents = True
    .Calculation = xlCalculationAutomatic
End With
End Sub

对我来说,his运行需要5-7分钟,而这需要1.5秒,其中我的第一个答案返回包含最接近匹配结果的一行。此sub也将返回大于或等于的所有值。

您可能需要调整输出的位置(假设结果应在单元格G3和下一个单元格中输出),但这应该运行得很快:

Sub subFindValue()

    Dim rngFound As Range
    Dim arrResults() As Variant
    Dim varFind As Variant
    Dim dCompare As Double
    Dim ResultIndex As Long
    Dim strFirst As String

    varFind = Range("E3").Text
    dCompare = Range("F3").Value2

    Range("G3:G" & Rows.Count).ClearContents

    With Range("TABL").Resize(, 1)
        Set rngFound = .Find(varFind, .Cells(.Cells.Count), xlValues, xlWhole)
        If Not rngFound Is Nothing Then
            ReDim arrResults(1 To WorksheetFunction.CountIf(.Cells, varFind), 1 To 1)
            strFirst = rngFound.Address
            Do
                If rngFound.Offset(, 1).Value > dCompare Then
                    ResultIndex = ResultIndex + 1
                    arrResults(ResultIndex, 1) = rngFound.Offset(, 2).Text
                End If
                Set rngFound = .Find(varFind, rngFound, xlValues, xlWhole)
            Loop While rngFound.Address <> strFirst
        End If
    End With

    If ResultIndex > 0 Then Range("G3").Resize(ResultIndex).Value = arrResults

End Sub
子子索引值()
暗淡的rngFound As范围
Dim arresults()作为变量
Dim varFind作为变体
将Dim数据比较为双精度
Dim ResultIndex尽可能长
Dim strFirst作为字符串
varFind=范围(“E3”)。文本
D比较=范围(“F3”)。值2
范围(“G3:G”和Rows.Count)。ClearContent
带范围(“TABL”)。调整大小(,1)
设置rngFound=.Find(varFind、.Cells(.Cells.Count)、xlValues、xlWhole)
如果不是,那么rngFound什么都不是
ReDim arrResults(1到WorksheetFunction.CountIf(.Cells,varFind),1到1)
strFirst=rngFound.Address
做
如果rngFound.Offset(,1).Value>dCompare,则
ResultIndex=ResultIndex+1
arrResults(ResultIndex,1)=rngFound.Offset(,2).Text
如果结束
设置rngFound=.Find(varFind、rngFound、xlValues、xlWhole)
在rngFound.Address strFirst时循环
如果结束
以
如果ResultIndex>0,则范围(“G3”).Resize(ResultIndex).Value=arrResults
端接头

您可能需要调整输出的位置(它假设结果应在单元格G3和向下输出),但这应该运行得非常快:

Sub subFindValue()

    Dim rngFound As Range
    Dim arrResults() As Variant
    Dim varFind As Variant
    Dim dCompare As Double
    Dim ResultIndex As Long
    Dim strFirst As String

    varFind = Range("E3").Text
    dCompare = Range("F3").Value2

    Range("G3:G" & Rows.Count).ClearContents

    With Range("TABL").Resize(, 1)
        Set rngFound = .Find(varFind, .Cells(.Cells.Count), xlValues, xlWhole)
        If Not rngFound Is Nothing Then
            ReDim arrResults(1 To WorksheetFunction.CountIf(.Cells, varFind), 1 To 1)
            strFirst = rngFound.Address
            Do
                If rngFound.Offset(, 1).Value > dCompare Then
                    ResultIndex = ResultIndex + 1
                    arrResults(ResultIndex, 1) = rngFound.Offset(, 2).Text
                End If
                Set rngFound = .Find(varFind, rngFound, xlValues, xlWhole)
            Loop While rngFound.Address <> strFirst
        End If
    End With

    If ResultIndex > 0 Then Range("G3").Resize(ResultIndex).Value = arrResults

End Sub
子子索引值()
暗淡的rngFound As范围
Dim arresults()作为变量
Dim varFind作为变体
将Dim数据比较为双精度
Dim ResultIndex尽可能长
Dim strFirst作为字符串
varFind=范围(“E3”)。文本
D比较=范围(“F3”)。值2
范围(“G3:G”和Rows.Count)。ClearContent
带范围(“TABL”)。调整大小(,1)
设置rngFound=.Find(varFind、.Cells(.Cells.Count)、xlValues、xlWhole)
如果不是,那么rngFound什么都不是
ReDim arrResults(1到WorksheetFunction.CountIf(.Cells,varFind),1到1)
strFirst=rngFound.Address
做
如果rngFound.Offset(,1).Value>dCompare,则
ResultIndex=ResultIndex+1
arrResults(ResultIndex,1)=rngFound.Offset(,2).Text
如果结束
设置rngFound=.Find(varFind、rngFound、xlValues、xlWhole)
在rngFound.Address strFirst时循环
如果结束
以
如果ResultIndex>0,则范围(“G3”).Resize(ResultIndex).Value=arrResults
端接头

计算公式,然后将结果粘贴到单元格中?您考虑过吗?当计算公式后出现值时,复制粘贴。问题是在任何情况下,每个单元格的公式计算都需要48小时以上(每个单元格更新至少需要1秒)因此,在上面粘贴的图像中,只有一个测试数据(金,2.5),在实际中有400000个这样的记录要从300000个查找表中搜索出来。考虑VBA解决方案而不是数组函数,或者任何内置函数。