Excel 自定义函数数据类型错误-为什么?还有如何调试?

Excel 自定义函数数据类型错误-为什么?还有如何调试?,excel,vba,Excel,Vba,我已经编写了一个自定义函数,不知道如何解决这个问题。 如果有人知道它出错的原因,我肯定会感兴趣,这样我就可以让它工作了。 但本着学习钓鱼的精神,我还需要知道下次如何自己解决这个问题。如果我将其更改为sub并取消对testvariables部分的注释(并在末尾注释function=行,这样sub就不会抱怨它),那么我会完美地使用它 如果我转到工作表并将函数放入一个单元格中,该单元格的信息与测试部分中的信息相同,则会抛出错误的数据类型错误。我试着设置断点来逐步完成,但显然没有达到ScreenUpda

我已经编写了一个自定义函数,不知道如何解决这个问题。 如果有人知道它出错的原因,我肯定会感兴趣,这样我就可以让它工作了。 但本着学习钓鱼的精神,我还需要知道下次如何自己解决这个问题。如果我将其更改为sub并取消对testvariables部分的注释(并在末尾注释function=行,这样sub就不会抱怨它),那么我会完美地使用它

如果我转到工作表并将函数放入一个单元格中,该单元格的信息与测试部分中的信息相同,则会抛出错误的数据类型错误。我试着设置断点来逐步完成,但显然没有达到ScreenUpdate=false

如果有关系的话,我经常在帖子中看到它的作用,所以我想我应该先发制人。如果没有关系,请跳过此部分。:-) 基本上,它会翻转vlookup,以便=InvertDVLookup(Q25:Q43,R25:V43,N25,5)将单元格N25视为字符串,然后使用Q25:Q43中的字符串列表作为子字符串搜索的一部分。如果找到匹配项,则返回匹配项所在的第5列中的值。如果未找到匹配项,则逐行查看r25:v43中的值,展开逗号分隔行以查找匹配项最多的行。它适用于没有标准化文本的订单

因此,N25中的红色消防车truck001将被列Q中的零件清单反复查看,如果有truck001,它将返回列5(价格)。如果没有,它将通过r:v查找任何有卡车的车辆,然后任何有卡车的车辆将查看颜色和其他描述符。这样,如果我们得到红色消防车卡车001或卡车,火,红色卡车001,它会找到它。同样,如果我们一直看到相同的缩写或拼写错误,我们可以用逗号分隔,这样red和redd就可以在两者位于同一单元格时找到匹配项

Public Function InvertedVLookup(Substrings_Array As Variant, Table_Array As Variant, Target_String As String, Column_Index_To_Return As Integer, Optional Approx_Match As Boolean = True)
'by rodger.tampa@gmail.com

    Application.ScreenUpdating = False

    Dim sResult
    Dim LB As Integer, UB As Integer, LB2 As Integer, UB2 As Integer, iMax As Integer
    Dim bDuplicate As Boolean
    Dim ws As Worksheet
    Dim aExpanded_Table_Array
    Set ws = ActiveSheet
    Dim aTableDelimitersExpanded()
    Dim aApproxMatch() As Integer

    '    ' =========== test variables ==== comment out when using function instead of sub ==============
    '    Dim Substrings_Array  As Variant
    '    Dim Table_Array  As Variant
    '    Dim Target_String As String
    '    Dim Column_Index_To_Return As Integer
    '    Dim Approx_Match As Boolean
    '    Substrings_Array = ws.Cells.Range("Q25:Q43")
    '    Table_Array = ws.Cells.Range("R25:V43")
    '    Target_String = ws.Cells.Range("N26").Value
    '    Column_Index_To_Return = 5
    '    Approx_Match = True
    '    ' =========== test variables ==== comment out when using function instead of sub ==============


    bDuplicate = False
    iMax = 0

        LB = LBound(Substrings_Array)
        UB = UBound(Substrings_Array)
        LB2 = LBound(Table_Array, 2)
        UB2 = UBound(Table_Array, 2)

    Dim strTemp As String
    For i = LB To UB
        If IsNull(Substrings_Array(i, 1)) = False Then
            If InStr(LCase(Target_String), LCase(Substrings_Array(i, 1))) > 0 Then
                sResult = i
                Exit For
            End If
        Else
            sResult = "Target String Null"
            GoTo ErrorHandling
        End If
    Next i

    If IsEmpty(sResult) = True Then
        If Approx_Match = True Then
            ReDim Preserve aTableDelimitersExpanded(LB To UB, LB2 To UB2)
            ReDim aApproxMatch(1 To UB, 1 To 1)
            Dim str
            Dim strSplit() As String

            'Check for and total the number of matching qualifiers
            For i = LB To UB
                For j = LBound(Table_Array, 2) To UBound(Table_Array, 2)
                    strSplit = Split(Table_Array(i, j), ", ")
                    For k = LBound(strSplit) To UBound(strSplit)
                        If IsNull(strSplit(k)) = False Then
                            If InStr(LCase(Target_String), LCase(strSplit(k))) > 0 Then
                                aApproxMatch(i, 1) = aApproxMatch(i, 1) + 1
                            End If
                        End If
                    Next k
                Next j
            Next i

            'look at aApproxMatch table for highest value to indicate best match
            For i = LB To UB
                If aApproxMatch(i, 1) > iMax Then
                    iMax = aApproxMatch(i, 1)
                    sResult = i
                    bDuplicate = False
                ElseIf aApproxMatch(i, 1) = iMax Then
                    bDuplicate = True
                End If
            Next i

            'check for ties based on qualifiers
            If bDuplicate = True Then
                sResult = "Multiple Matches"
                GoTo ErrorHandling
            End If
        Else
            sResult = "No Match"
            GoTo ErrorHandling
        End If
    End If

    'return the result
    sResult = Table_Array(sResult, Column_Index_To_Return)

ErrorHandling:
    'If sResult = "Target String Null"
    'If sResult = "No Match"
    'If sResult = "Multiple Matches"

    InvertedVLookup = sResult
    Application.ScreenUpdating = True
End Function

这应该按需要工作:

Public Function InvertedVLookup(Substrings_Array As Variant, Table_Array As Variant, Target_String As String, Column_Index_To_Return As Integer, Optional Approx_Match As Boolean = True)
  Dim sResult
  Dim Bou(2) As Long
  Dim aApproxMatch() As Integer
  Dim strSplit() As String
  Bou(0) = LBound(Substrings_Array.Value)
  Bou(1) = UBound(Substrings_Array.Value)
  For i = Bou(0) To Bou(1)
    If IsNull(Substrings_Array(i, 1)) Then
      InvertedVLookup = "Target String Null"
      Exit Function
    Else
      If InStr(LCase(Target_String), LCase(Substrings_Array(i, 1))) Then
     'If InStr(1, Target_String, Substrings_Array(i, 1), 1) Then '<~~~ better use this than LCase
        sResult = i
        Exit For
      End If
    End If
  Next i
  If IsEmpty(sResult) Then
    If Approx_Match Then
      ReDim aApproxMatch(1 To Bou(1), 1 To 1)
      For i = Bou(0) To Bou(1)
        For j = LBound(Table_Array.Value, 2) To UBound(Table_Array.Value, 2)
          strSplit = Split(Table_Array(i, j), ", ")
          For k = LBound(strSplit) To UBound(strSplit)
            If Not IsNull(strSplit(k)) Then
              If InStr(LCase(Target_String), LCase(strSplit(k))) Then
             'If InStr(1, Target_String, strSplit(k), 1) Then '<~~~ better use this than LCase
                aApproxMatch(i, 1) = aApproxMatch(i, 1) + 1
              End If
            End If
          Next k
        Next j
      Next i
      For i = Bou(0) To Bou(1)
        If aApproxMatch(i, 1) > Bou(2) Then
          Bou(2) = aApproxMatch(i, 1)
          sResult = i
        ElseIf aApproxMatch(i, 1) = Bou(2) Then
          InvertedVLookup = "Multiple Matches"
          Exit Function
        End If
      Next i
    Else
      InvertedVLookup = "No Match"
      Exit Function
    End If
  End If
  InvertedVLookup = Table_Array(sResult, Column_Index_To_Return)
End Function
Public Function invertDVlookup(子字符串\u数组为变量,表\u数组为变量,目标字符串为字符串,列\u索引\u To \u返回为整数,可选近似匹配为布尔值=True)
暗淡的结果
暗色花束(2)一样长
Dim aApproxMatch()为整数
Dim strSplit()作为字符串
Bou(0)=LBound(子字符串\u数组值)
Bou(1)=UBound(子字符串\u数组值)
对于i=Bou(0)到Bou(1)
如果IsNull(子串数组(i,1)),那么
InvertDVLookup=“目标字符串为空”
退出功能
其他的
如果InStr(LCase(Target_String)、LCase(substring_Array(i,1)),那么

'如果InStr(1,Target_String,substring_Array(i,1),1),那么'我不在乎。在很多网站上,它总是被刮伤。:-)没有纸来测试它,使它几乎不可能测试。。。但是,有时像
UBound()
这样的简单函数在与范围一起使用时会弹出错误。。。有一个范围,我总是按如下方式使用它:
LB=LBound(Substrings\u Array.Values)
。。。如果那没用,请给我一本练习册:)我试试看。谢谢你的回复!行动
LB=LBound(Substrings\u Array.Value)
(没有
s
)我是将值粘贴在这里还是以某种方式发送工作簿?这太棒了!非常感谢你。知道是什么导致了数据类型错误吗?@Rodger every
LBound/Ubound
用于不带
值的范围(或
.Formula
或任何内容)。。。变量不存在时出现另一个错误。。。但是我不记得在哪里。。。对不起:(不用担心。我刚意识到我忘了把它标对,然后再次说谢谢!