VBA:函数给出;运行时错误';424';:“所需对象”;调用时出错

VBA:函数给出;运行时错误';424';:“所需对象”;调用时出错,vba,excel,basic,Vba,Excel,Basic,我有两个主要功能,第一个是搜索银行。它逐单元格搜索Credits、Type和store列,找出是否匹配。如果匹配,则返回True,并作为副作用更改匹配单元格的颜色 我用来测试第一个函数的第二个子函数。 我遇到的问题是,我得到了一个运行时错误“424”:需要对象,没有问题所在的指示 以下是第一个函数: Function search_bank(Store As String, amount As Double, Amex As Boolean) As Boolean Dim m_store

我有两个主要功能,第一个是搜索银行。它逐单元格搜索Credits、Type和store列,找出是否匹配。如果匹配,则返回True,并作为副作用更改匹配单元格的颜色

我用来测试第一个函数的第二个子函数。 我遇到的问题是,我得到了一个运行时错误“424”:需要对象,没有问题所在的指示

以下是第一个函数:

Function search_bank(Store As String, amount As Double, Amex As Boolean) As Boolean
    Dim m_store As Range
    Dim m_type As Range
    Dim Credit_Amt_Col As Range

    Set m_store = bank_sheet.Range("1:1").Find("M_STORE")
    Set m_type = bank_sheet.Range("1:1").Find("M_TYPE")
    Set Credit_Amt_Col = bank_sheet.Range("1:1").Find("Credit Amt")

    search_bank = False
    Dim i As Long
    For i = 1 To 9000
        If Not search_bank Then
            Dim store_cell As Range
            Dim type_cell As Range
            Dim credit_cell As Range

            Set store_cell = Worksheets(2).Cells(i, m_store.Column)
            Set type_cell = Worksheets(2).Cells(i, m_type.Column)
            Set credit_cell = Worksheets(2).Cells(i, Credit_Amt_Col.Column)

            If InStr(UCase(store_cell.Value), UCase(Store)) > 0 And credit_cell.Value = amount Then
                If store_cell.Interior.ColorIndex <> 46 Then
                    If Amex And InStr(UCase(type_cell.Value), UCase("amex deposit")) Then
                        store_cell.Interior.ColorIndex = 46
                        search_bank = True

                    End If
                    If Not Amex And InStr(UCase(type_cell.Value), UCase("Credit Card Deposit")) Then
                        store_cell.Interior.ColorIndex = 46
                        search_bank = True

                    End If
                End If
            End If
        End If
    Next i

End Function
我已尝试在测试仪上使用“set”:

Sub Tester()
    Dim x As Boolean
    x = search_bank("ctc", 38.4, True)
    Debug.Print (x)
End Sub
Sub Tester()
    Dim x As Boolean
    Set x = search_bank("ctc", 38.4, True)
    Debug.Print (x)
End Sub
甚至在向测试仪传递变量之前声明变量(我不太习惯VBA,但有一段时间我认为它太古老了,需要在传递之前声明)


如果可以的话,我会将此作为评论发布,但我不能。所以我知道这不会直接解决问题,但会有助于调试。见下文:

Function search_bank(Store As String, amount As Double, Amex As Boolean) As Boolean
Dim m_store As Range
Dim m_type As Range
Dim Credit_Amt_Col As Range

' It is always best to check the inverse of an object before setting
' setting an object variable to the target object. In this case
' I check to make sure each range can be found, and if not, I
' debug.print which variable cannot be set.

Set m_store = bank_sheet.Range("1:1").Find("M_STORE")
Set m_type = bank_sheet.Range("1:1").Find("M_TYPE")
Set Credit_Amt_Col = bank_sheet.Range("1:1").Find("Credit Amt")

If m_store is Nothing then Debug.Print "m_store is nothing"
If m_type is Nothing then Debug.Print "m_type is nothing"
If Credit_Amt_Col is Nothing then Debug.Print "Credit_Amt_Col is nothing."

search_bank = False
Dim i As Long
For i = 1 To 9000
    If Not search_bank Then
        Dim store_cell As Range
        Dim type_cell As Range
        Dim credit_cell As Range

        ' Use the inverse method above on these three items as well.
        Set store_cell = Worksheets(2).Cells(i, m_store.Column)
        Set type_cell = Worksheets(2).Cells(i, m_type.Column)
        Set credit_cell = Worksheets(2).Cells(i, Credit_Amt_Col.Column)

        If InStr(UCase(store_cell.Value), UCase(Store)) > 0 And credit_cell.Value = amount Then
            If store_cell.Interior.ColorIndex <> 46 Then
                If Amex And InStr(UCase(type_cell.Value), UCase("amex deposit")) Then
                    store_cell.Interior.ColorIndex = 46
                    search_bank = True

                End If
                If Not Amex And InStr(UCase(type_cell.Value), UCase("Credit Card Deposit")) Then
                    store_cell.Interior.ColorIndex = 46
                    search_bank = True

                End If
            End If
        End If
    End If
Next i

End Function
函数搜索\u bank(存储为字符串,金额为双精度,美国运通为布尔值)为布尔值
暗淡的m_存储范围
Dim m_类型As范围
调暗信用金额作为范围
'设置前最好检查对象的反转
'将对象变量设置为目标对象。在这种情况下
我检查以确保每个范围都能找到,如果找不到,我会
'debug.print无法设置哪个变量。
设置m_商店=银行工作表范围(“1:1”)。查找(“m_商店”)
设置m_类型=银行工作表范围(“1:1”)。查找(“m_类型”)
设置贷方金额=银行工作表范围(“1:1”)。查找(“贷方金额”)
如果m_store为Nothing,则调试。打印“m_store为Nothing”
如果m_类型为Nothing,则调试。打印“m_类型为Nothing”
如果信用金额为零,则调试。打印“信用金额为零”
search\u bank=False
我想我会坚持多久
对于i=1至9000
如果不搜索银行,则
Dim存储单元作为范围
Dim类型_单元作为范围
调暗信用单元作为范围
'在这三个项目上也使用上述相反的方法。
设置存储单元=工作表(2).Cells(i,m\u存储单元.Column)
集合类型\单元=工作表(2).单元(i,m\类型.列)
设置信用单元=工作表(2).单元(i,信用金额列)
如果InStr(UCase(store_cell.Value)、UCase(store))>0且credit_cell.Value=金额,则
如果存储_cell.Interior.ColorIndex 46,则
如果美国运通和InStr(UCase(类型单元格值)、UCase(“美国运通存款”)),则
store_cell.Interior.ColorIndex=46
search\u bank=True
如果结束
如果不是美国运通和InStr(UCase(类型单元格值)、UCase(“信用卡存款”)),则
store_cell.Interior.ColorIndex=46
search\u bank=True
如果结束
如果结束
如果结束
如果结束
接下来我
端函数

我内联发布了一条评论,但基本上我为前三个对象添加了一个反向检查(您也希望对第二组对象执行此操作)。这是最佳实践,但在这种情况下,它也(希望)能帮助您精确定位无法找到对象的位置。

您的OP下面有很多好的评论,还有@BrandonBarney的答案,但这是我的两分钱:

第一部分:我看到的最大的一件事是,在设置范围对象时,你从不声明
空白表
。这就是你的错误的来源。它正在寻找
范围(“1:1”)。查找(“M_商店”)
,但不知道
银行表是什么

第二部分:向您指出这一点的一个快速方法是在代码的顶部。这样可以确保显式声明您使用的任何变量。即:

Option Explicit

Function search_bank(Store As String, amount As Double, Amex As Boolean) As Boolean
    Dim m_store As Range
    Dim m_type As Range
    Dim Credit_Amt_Col As Range

    ''''' New code here: ''''''
    Dim bank_sheet as Worksheet
    Set bank_sheet = Worksheets("Bank Sheet") ' change to whatever the name is.
    '''''''''''''''''''''''''''
    Set m_store = bank_sheet.Range("1:1").Find("M_STORE")
    Set m_type = bank_sheet.Range("1:1").Find("M_TYPE")
    Set Credit_Amt_Col = bank_sheet.Range("1:1").Find("Credit Amt")
    ' etc. etc.
Option Explicit
在您意外输入错误时也会有所帮助。因此,如果你曾经做过
bank\u sheet.Range(“A:A”)
,它会出错并要求你声明
bank\u sheet
。或者,当然,你会意识到这是一个打字错误,然后修复它

奖金分:通过组合
Dim
s:
Dim m mu store as Range、m mu type as Range、Credit金额Col as Range
都可以在一行上


(注意:执行
Dim m mu store、m mu type、Credit mu Amt Col as Range
操作将not将所有三个设置为
Range
type。它将使
m mu store
m mu type
成为
变量,因为它没有声明。在这种情况下,只有
Credit mu Amt\Col
将是
范围。因此您仍然需要明确说明。)当您得到运行时错误时,选择调试选项并使用F8单步执行代码,直到您看到错误所在的行。您在何处/何时/如何声明
bank\u sheet
?另外,请确保三个
Find
方法的结果返回有效对象。如果在第1行中找不到这些值,则它们将返回一个
Nothing
,这将在以后的代码中引发此错误。
范围。Find
可以返回
Nothing
。您必须测试返回值。@RyanFrancis FWIW您确实有一个免费的全局工作表对象。查看项目浏览器工具窗口;工作表节点显示为
Sheet1(Sheet1)
-这是
CodeName(WorksheetName)
,其中
CodeName
是一个全局范围
工作表
对象变量,您可以免费获得。通过更改
(名称)
属性,您可以在properties toolwindow(F4)中控制其名称。设置对象变量
会更容易,然后只需测试
(如果Set m_store为Nothing
等)。开销也会更小,并且“硬编码”更少字符串文本。如果尝试使用not after set,如果find未返回对象,则可能会遇到“对象变量not set”错误。这是反转区块的初衷。此外,我会理想地消除硬编码的字符串文字,如果可能的话,可能使用listobject而不是Find,但这不是Codereview。
Option Explicit

Function search_bank(Store As String, amount As Double, Amex As Boolean) As Boolean
    Dim m_store As Range
    Dim m_type As Range
    Dim Credit_Amt_Col As Range

    ''''' New code here: ''''''
    Dim bank_sheet as Worksheet
    Set bank_sheet = Worksheets("Bank Sheet") ' change to whatever the name is.
    '''''''''''''''''''''''''''
    Set m_store = bank_sheet.Range("1:1").Find("M_STORE")
    Set m_type = bank_sheet.Range("1:1").Find("M_TYPE")
    Set Credit_Amt_Col = bank_sheet.Range("1:1").Find("Credit Amt")
    ' etc. etc.