使用 VBA for Excel 在 UDF 中输入的名称无效

Posted

技术标签:

【中文标题】使用 VBA for Excel 在 UDF 中输入的名称无效【英文标题】:Invalid name entered in UDF with VBA for Excel 【发布时间】:2017-01-25 17:17:23 【问题描述】:

我正在制作一个简单的 UDF,用于检查给定国家/地区是否是经合组织的成员。我有两个输入:

    包含国家名称的 Excel 单元格

    包含所有 OECD 国家的列的第一个单元格的输入。

该函数通过循环比较单元格Candidatecountries 列的内容。如果候选人名称与任何 OECD 国家都不匹配,则函数最终将其归类为非 OECD 国家。

我的代码是这样的:

Function OECD(Candidate, Countries)
    Dim Candidate As String
    Dim Countries As String
    OECDCountry = Countries 'Variable that changes at every iteration, I compare the name of the candidate to this
    For i = 1 To 34     
        If Candidate.Value = OECDCountry Then
            OECD = 2                 
        Else: OECDCountry = Countries.Offset(i, 0)
    Next i

'If the column next to the candidate name, where I am running this function, is still empty, record the country as non-OECD

    If Candidate.Offset(0, 1) <> 2 Then OECD = 1                
End Function

但是,当我尝试使用该功能时,在选择第二个输入时收到以下错误消息:

您输入的名称无效。原因可能包括:

-名称不以字母或下划线开头

-名称中包含空格或其他无效字符

-名称与 Excel 内置名称或工作簿中另一个对象的名称冲突

为什么我会收到此错误消息,我该如何解决?

【问题讨论】:

您的范围内有重复的名称。您要求将变量 CandidateCountries 作为参数传递给您的函数,然后在函数本身中声明具有相同名称的变量。这些不能是相同的名称,这可能是您问题的一部分。然后,当您尝试使用 Dim Candidate As String 并且字符串变量没有 .Value 属性时,您还尝试使用 Candidate.Value(尽管传递的参数可以作为单元格引用传递)。 你应该考虑使用第二个参数Countries As Range,会让你的UDF代码简单很多 并且您应该将OECDCountry 声明为String。您需要将您的 UDF 声明为 Volatile,以便更改列出所有国家/地区的列将允许重新调用您的 UDF。您是否考虑过使用VLOOKUP 来做所有事情而不需要 UDF? 【参考方案1】:

嗯,我必须说,我认为经合组织国家是静态数据的一个例子,因为它不会经常变化。我会将数据存储在某处的工作表上,然后在第一次请求时使用 Scripting.Dictionary 将其读入缓存,然后可以使用 Exists 方法。这是我的解决方案

Option Explicit

Private mdicRunTimeCacheOECDCountries As Scripting.Dictionary

Sub DevTimeSetup_RunOnce()

    ' ___          _____ _           ___      _               ___           ___
    '|   \ _____ _|_   _(_)_ __  ___/ __| ___| |_ _  _ _ __  | _ \_  _ _ _ / _ \ _ _  __ ___
    '| |) / -_) V / | | | | '  \/ -_)__ \/ -_)  _| || | '_ \ |   / || | ' \ (_) | ' \/ _/ -_)
    '|___/\___|\_/  |_| |_|_|_|_\___|___/\___|\__|\_,_| .__/_|_|_\\_,_|_||_\___/|_||_\__\___|
    '                                                 |_| |___|                                           http://www.network-science.de/ascii/
    '* just some code to set up a sheet with some data as OP supplied none
    '* so that anyone can play with this problem
    Dim rngOECD As Excel.Range
    Set rngOECD = Sheet1.Range(Sheet1.Cells(1, 1), Sheet1.Cells(7, 1))
    rngOECD.Value2 = ["USA";"UK";"Germany";"France";"Italy";"Japan";"Canada"] 'not full OECD, just G7
    rngOECD.Name = "OECDCountries"

End Sub


Private Function GetRunTimeCacheOECDCountries() As Scripting.Dictionary
    If mdicRunTimeCacheOECDCountries Is Nothing Then
        Set mdicRunTimeCacheOECDCountries = New Scripting.Dictionary

        Dim rngOECD As Excel.Range
        Set rngOECD = Sheet1.Range("OECDCountries")

        Dim rngLoop As Excel.Range
        For Each rngLoop In rngOECD
            mdicRunTimeCacheOECDCountries.Add rngLoop.Value2, 0
        Next

    End If
    Set GetRunTimeCacheOECDCountries = mdicRunTimeCacheOECDCountries
End Function



Public Function OECD(Candidate) As Long
    OECD = VBA.IIf(GetRunTimeCacheOECDCountries.Exists(Candidate), 1, 0)
End Function

并使用像这样的单元格公式从工作表调用

=OECD("UK")

【讨论】:

感谢您的回答。这比我预期的要困难,但现在我想我明白了

以上是关于使用 VBA for Excel 在 UDF 中输入的名称无效的主要内容,如果未能解决你的问题,请参考以下文章

VBA Excel UDF保留原始值

Excel VBA UDF 自动完成参数

Excel VBA:通过突出显示颜色重新计算UDF总和

Excel VBA:不满足条件时如何让UDF返回0

将多维数组传递到 VBA 中的 Excel UDF

我在 Excel VBA 中使用“InBetween”UDF,它适用于 43 行,然后停止工作