识别VBA UDF的两个颈部

识别VBA UDF的两个颈部,vba,excel,performance,runtime,Vba,Excel,Performance,Runtime,在我的工作表中,我有四个不同的类别。对于每个类别,都有 3~5种不同的价格。还有其他属性。因此,每个类别重复了多次,总共有30000行。工作表的第一行包含所有列名。每个类别跨越连续的行。因此,我编写了以下函数来识别“块”并计算“块”的最小值 Public Function blockMin(rng_temp作为范围)作为整数 暗咖喱和长咖喱一样 currRow=rng_临时行 '查找类别列 变暗rng As范围 昏暗的小屋和长的一样 暗淡的价格 对于范围内的每个rng(“1:1”) 如果rng

在我的工作表中,我有四个不同的类别。对于每个类别,都有 3~5种不同的价格。还有其他属性。因此,每个类别重复了多次,总共有30000行。工作表的第一行包含所有列名。每个类别跨越连续的行。因此,我编写了以下函数来识别“块”并计算“块”的最小值

Public Function blockMin(rng_temp作为范围)作为整数
暗咖喱和长咖喱一样
currRow=rng_临时行
'查找类别列
变暗rng As范围
昏暗的小屋和长的一样
暗淡的价格
对于范围内的每个rng(“1:1”)
如果rng.Value=“Cat”,则
类别列=rng.列
如果结束
如果rng.Value=“价格”,则
pric_col=标记列
如果结束
下一个rng
Dim cat_col_char,price_col作为字符串
cat\u col\u char=数字2个字母(cat\u col)
price\u col\u char=number2字母(price\u col)
'查找usedRange的最后一行
最后一排一样长
lastRow=findLastRow()
'每个猫的挡块在哪里
暗淡的起点,终点和长的一样
startRow=rng_温度行
endRow=rng_临时行
“找到顶端
开始时执行此操作>=2
如果范围(cat\u col\u char和startRow)。值范围(cat\u col\u char和currRow),则
startRow=startRow+1
退出Do
如果结束
startRow=startRow-1
环
如果startRow=1,则startRow=2'位于最顶部
"找底"

在endRow时执行类似操作会快一点:

Public Function blockMin(rng_temp As Range) As Integer 'double?

    Dim sht As Worksheet, rS As Long, rE As Long, cat, v
    Dim hdrs, i As Long
    Dim cat_col As Long, price_col As Long

    Set sht = rng_temp.Worksheet '<<< scope all references to this sheet
                                 ' or you'll get odd results when a different
                                 ' sheet is active
    rS = rng_temp.Row
    rE = rS

    'Find headers
    hdrs = sht.Range("A1").Resize(1, 100).Value 'limit your search range
    For i = 1 To UBound(hdrs, 2)
        v = hdrs(1, i)

        If cat_col = 0 And v = "Cat" Then cat_col = i
        If price_col = 0 And v = "Price" Then price_col = i

        If cat_col > 0 And price_col > 0 Then
            cat = rng_temp.EntireRow.Cells(cat_col).Value
            If Len(cat) > 0 Then
                'find start/end rows
                Do While rS > 1 And sht.Cells(rS, cat_col) = cat
                    rS = rS - 1
                Loop
                Do While sht.Cells(rE, cat_col) = cat
                    rE = rE + 1
                Loop

                blockMin = Application.Min(sht.Range(sht.Cells(rS + 1, price_col), _
                                                     sht.Cells(rE - 1, price_col)))
            End If
            Exit For
        End If
    Next i

End Function
Public Function blockMin(rng_temp作为范围)作为整数“double”?
尺寸sht为工作表,rS为长,rE为长,cat为v
暗淡的HDR,我想
暗淡的颜色和颜色一样长,价格和颜色一样长
设置sht=rng_临时工作表'1和sht.单元格(rS、cat_col)=cat
rS=rS-1
环
当短单元格(rE、cat_col)=cat
rE=rE+1
环
blockMin=Application.Min(短范围(短单元格(rS+1,价格列))_
单格(rE-1,价格)
如果结束
退出
如果结束
接下来我
端函数

可能值得将
Option Explicit
放在模块顶部,修复未声明/键入的变量,然后重新发布代码。
对于范围内的每个rng(“1:1”)
-您正在检查约16000个单元格(两次)对于每个调用-当
cat\u col
price\u col
都大于0时,您应该退出循环。我想如果您将其转换为Sub,而不是将其用作UDF,则速度会快得多-每个调用都有大量重复。从简单的一瞥中,您对代码的描述并不是100%清楚实现(我仍然无法想象一个块是什么),通过在数据中使用透视表,您可能会受益。该块在问题主体中显示为链接。很抱歉,我刚开始使用这个帐户,所以我没有被授权发布图片,但只有URL…除了随机命名的变量之外,
rS
rE
是什么?不是随机的,只是简短:“rowStart”,“rowEnd”好的-那么为什么这么短而不是描述性的名称?因为这是我编写代码时喜欢的?它不是那么难以理解。谢谢你的评论!有没有办法让我克服这个循环部分?我想这就是瓶颈。
Public Function blockMin(rng_temp As Range) As Integer 'double?

    Dim sht As Worksheet, rS As Long, rE As Long, cat, v
    Dim hdrs, i As Long
    Dim cat_col As Long, price_col As Long

    Set sht = rng_temp.Worksheet '<<< scope all references to this sheet
                                 ' or you'll get odd results when a different
                                 ' sheet is active
    rS = rng_temp.Row
    rE = rS

    'Find headers
    hdrs = sht.Range("A1").Resize(1, 100).Value 'limit your search range
    For i = 1 To UBound(hdrs, 2)
        v = hdrs(1, i)

        If cat_col = 0 And v = "Cat" Then cat_col = i
        If price_col = 0 And v = "Price" Then price_col = i

        If cat_col > 0 And price_col > 0 Then
            cat = rng_temp.EntireRow.Cells(cat_col).Value
            If Len(cat) > 0 Then
                'find start/end rows
                Do While rS > 1 And sht.Cells(rS, cat_col) = cat
                    rS = rS - 1
                Loop
                Do While sht.Cells(rE, cat_col) = cat
                    rE = rE + 1
                Loop

                blockMin = Application.Min(sht.Range(sht.Cells(rS + 1, price_col), _
                                                     sht.Cells(rE - 1, price_col)))
            End If
            Exit For
        End If
    Next i

End Function