繁体   English   中英

Excel VBA:UDF 导致#NAME? 从单元格调用时出错

[英]Excel VBA: UDF results in #NAME? error when called from cell

我从本指南中复制了一些符合我目的的 UDF function 代码,据说这些代码对其他人有用。 我并没有真正改变代码,但为了透明,这里是我在工作簿中作为模块的确切代码:

Function IsExtWorkBookOpen(Name As String) As Boolean
    Dim xWb As Workbook
    On Error Resume Next
    Set xWb = Application.Workbooks.Item(Name)
    IsExtWorkBookOpen = (Not xWb Is Nothing)
End Function

现在,当我在工作簿的单元格中输入 function 时,function 将作为选项出现在下拉列表中。 我按下制表符自动填充 UDF 的全名,以确保正确键入 function 名称。 然后,我在不同的单元格中多次调用 function 并使用不同的文件名/路径作为字符串,例如:

=IsExtWorkBookOpen("C:\Computer\Fake\filepath\name\CORRECTLY SPELLED FULL FILENAME.xlsm")
=IsExtWorkBookOpen("C:\Computer\Fake\filepath\name\[CORRECTLY SPELLED FULL FILENAME].xlsm")
=IsExtWorkBookOpen("[CORRECTLY SPELLED FULL FILENAME]")

尝试使用或不使用文件名周围的括号。 而且我已经在这里编辑了文件路径/名称,它是我代码中的实际文件路径和文件名。 请注意,我的代码中的文件路径指向的驱动器是网络目录,而不是 PC 硬件中的本地目录。

还尝试添加以下内容作为第二个参数: Optional VolatileParameter As Variant并调用 NOW() 作为第二个参数,以查看它是否与需要 volatile 的 UDF 有关。 令我沮丧的是,似乎没有任何效果,因为单元格中的结果值始终是#NAME。

不过这很奇怪,因为我在 VBA 编辑器中测试了我的代码,方法是插入一个过程,在过程中调用 UDF,在 UDF 中放置断点并运行该过程。 这是代码:

Public Sub Test1()
    Dim x
    x = IsExtWorkBookOpen("EXTERNAL WORKBOOK.xlsm")
    MsgBox (x)
End Sub

该过程完美运行,并返回 FALSE 值。 在断点期间无法注意到注册表中的任何内容。 尽管我确实注意到即使我正在检查的外部工作簿实际上是打开的,它似乎也会返回 FALSE ......所以这可能是一个比试图弄清楚为什么 function 在输入单元格时无法工作更大的问题。

更奇怪的是,我第一次将 function 输入到单元格中,它确实返回并显示 FALSE,但只是第一次。 自从#NAME。

我尝试爬取 web 寻找类似的编程错误,我发现最接近的是这个论坛帖子。 似乎与这个用户的 UDF 一样,我的甚至没有执行,因为 excel 从一开始就不知道如何执行它?

最后,我注意到“乔”在第一个网页上的以下评论,我从那里复制了代码,其中指出:

只是想确保每个人都知道,“IsWorkBookOpen”function 将只能判断当前 Excel 实例中是否打开了工作簿。 如果您打开了多个实例,则需要在每个实例上运行它,以确保工作簿(未)打开,仅使用此代码。

阅读此评论,此代码是否注定从一开始就为我的目的工作? 我仍然对此表示怀疑,因为即使我尝试使用当前工作簿(不是外部工作簿)(VBA 模块所在的工作簿)的正确拼写文件名调用 UDF,也会发生 #NAME 错误,这让我相信这个错误是代码功能的其他地方。

如果是这样,任何人都可以提示我需要什么代码才能成功执行我的 function 以检查是否在同一本地 PC/桌面中打开了另一个工作簿?

该 UDF 对我来说很好,但请注意Application.Workbooks.Item()需要工作簿名称而不是完整路径,所以

=IsExtWorkBookOpen("tempo3.xlsb") 

返回 TRUE 但

=IsExtWorkBookOpen("C:\Temp\tempo3.xlsb") 

给出错误。

请注意,如果您想了解工作簿是否在同一实例或 Excel 的不同实例中打开,您可以使用GetObject采取不同的方法(注意这里您将传递完整路径):

Function IsExtWorkBookOpen2(Name As String) As Boolean
    Dim xWb As Object
    On Error Resume Next
    Set xWb = GetObject(Name)
    If Not xWb Is Nothing Then Debug.Print xWb.Name
    IsExtWorkBookOpen2 = (Not xWb Is Nothing)
End Function

我建议你重写 function 如下:

Option Explicit



Function IsWorkbookOpenByName(name As String) As Boolean

Dim wb As Workbook
For Each wb In Application.Workbooks ' Loop through all open workbooks
    If wb.Name = name Then ' If a workbook is found with specified name (name + extension)...
        IsWorkbookOpenByName = True ' ... return true...
        Exit For ' ... and exit loop.
    End If
Next

End Function



Function IsWorkbookOpenByFullName(fullName As String) As Boolean
    
    Dim wb As Workbook
    For Each wb In Application.Workbooks ' Loop through all open workbooks
        If wb.FullName = fullName Then ' If a workbook is found with specified fullName (path + name + extension)...
            IsWorkbookOpenByFullName = True ' ... return true...
            Exit For ' ... and exit loop.
        End If
    Next
    
End Function

上面的代码已经过测试并且可以工作。

如果您只想将这些函数组合在一个中,只需将第一个 function 中的If语句更改为If wb.Name = name or wb.FullName = name

Option Explicit



Function IsWorkbookOpen(name As String) As Boolean

Dim wb As Workbook
For Each wb In Application.Workbooks ' Loop through all open workbooks
    If wb.Name = name or wb.FullName = name Then ' If a workbook is found with specified name or fullname...
        IsWorkbookOpen = True ' ... return true...
        Exit For ' ... and exit loop.
    End If
Next

End Function

使用最后一个 function,您可以传递名称或全名(名称 + 路径 + 扩展名)。

注 1:我强烈建议您对所有 VBA 代码使用Option Explicit 此预处理器命令强制 VBA 解释器(请记住 VBA 并未真正编译)要求所有变量声明。 这可以防止拼写错误,并且可以为您节省数小时的调试时间来寻找某个变量名中缺少的字符。 此外,它将使您的代码更可靠,这是一个健康的习惯。

注意 2:如果可能,请避免使用On Error Resume Next语句,因为它可能有害。 即使发生错误,该语句“授权”代码继续执行,因此您可能会从代码中获得意外结果,并且如果它是复杂的 function,则可能难以调试。

我这么说是因为 VBA 是我的第一个编程语言,不幸的是没有人告诉我这些方面。 我了解到改变坏习惯比按时学习好习惯更难:)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM