使用VBA与列表匹配的数据验证

使用VBA与列表匹配的数据验证,vba,excel,Vba,Excel,我在excel中有一定范围的单元格,我想在其中对另一个数据验证应用数据验证 我希望用户在单元格范围内只有3个数据输入选项: 要么是一个数字 一系列数字或数字 从包含单词和数字的下拉列表中选择 我已经使用以下功能实现了1号和2号: Function checkStr(ByVal str As String) As String Dim objRegEx As Object, allMatches As Object Set objRegEx = CreateObject("VBS

我在excel中有一定范围的单元格,我想在其中对另一个数据验证应用数据验证

我希望用户在单元格范围内只有3个数据输入选项:

  • 要么是一个数字
  • 一系列数字或数字
  • 从包含单词和数字的下拉列表中选择
  • 我已经使用以下功能实现了1号和2号:

    Function checkStr(ByVal str As String) As String
    
        Dim objRegEx As Object, allMatches As Object
        Set objRegEx = CreateObject("VBScript.RegExp")
    
        With objRegEx
            .MultiLine = False
            .IgnoreCase = False
            .Global = True
            .Pattern = "^\d+(-\d+)?$"
        End With
    
    
        Set allMatches = objRegEx.Execute(str)
        checkStr = (allMatches.Count > 0)
    
    End Function
    

    由于上述函数只允许输入数字或一系列数字,因此,您对如何添加验证以允许来自预定义列表(包含单词和数字)的值有何想法?

    该列表从某个范围中获取值。因此,获取列表的范围并使用
    应用程序.Match()
    检查
    str
    是否存在:

    Public Function checkStr(str As String) As Boolean
    
        Dim isItError As Variant
        isItError = Application.Match(str, Worksheets(1).Range("A1:A5"), 0)
    
        checkStr = Not IsError(isItError)
    
    End Function
    
    Application.Match()
    将返回
    error
    true
    。因此,可以使用
    而不是iError()来修复函数


    如果要将字符串与字符串和数字作为数字进行比较,请尝试将变量作为变量传递,并让VBA确定它实际上是什么:

    Public Function checkMe(someVar As Variant) As Boolean
    
        Dim isItError As Variant
        Dim formulaAddress As String
    
        With Range("C1").Validation
            formulaAddress = Right(.Formula1, Len(.Formula1) - 1)
        End With
    
        isItError = Application.Match(someVar, Range(formulaAddress))
        checkMe = Not IsError(isItError)
    
    End Function
    
    如果将变量显式定义为数字或字符串,则另一个选项将被排除在
    应用程序.Match()比较中:

    ?Application.Match("1",Array(1,2,3))
    Error 2042
    ?Application.Match(1,Array(1,2,3))
    1 
    ?Application.Match("1",Array("1","2","3"))
    1 
    ?Application.Match(1,Array("1","2","3"))
    Error 2042
    

    该列表从某个范围中获取值。因此,获取列表的范围并使用
    应用程序.Match()
    检查
    str
    是否存在:

    Public Function checkStr(str As String) As Boolean
    
        Dim isItError As Variant
        isItError = Application.Match(str, Worksheets(1).Range("A1:A5"), 0)
    
        checkStr = Not IsError(isItError)
    
    End Function
    
    Application.Match()
    将返回
    error
    true
    。因此,可以使用
    而不是iError()来修复函数


    如果要将字符串与字符串和数字作为数字进行比较,请尝试将变量作为变量传递,并让VBA确定它实际上是什么:

    Public Function checkMe(someVar As Variant) As Boolean
    
        Dim isItError As Variant
        Dim formulaAddress As String
    
        With Range("C1").Validation
            formulaAddress = Right(.Formula1, Len(.Formula1) - 1)
        End With
    
        isItError = Application.Match(someVar, Range(formulaAddress))
        checkMe = Not IsError(isItError)
    
    End Function
    
    如果将变量显式定义为数字或字符串,则另一个选项将被排除在
    应用程序.Match()比较中:

    ?Application.Match("1",Array(1,2,3))
    Error 2042
    ?Application.Match(1,Array(1,2,3))
    1 
    ?Application.Match("1",Array("1","2","3"))
    1 
    ?Application.Match(1,Array("1","2","3"))
    Error 2042
    

    我建议将返回值
    更改为布尔值
    ,然后根据有效列表项数组过滤
    str

    Function checkStr(ByVal str As String) As Boolean
    
        Dim objRegEx As Object, allMatches As Object
        Set objRegEx = CreateObject("VBScript.RegExp")
    
        With objRegEx
            .MultiLine = False
            .IgnoreCase = False
            .Global = True
            .Pattern = "^\d+(-\d+)?$"
        End With
    
        Set allMatches = objRegEx.Execute(str)
    
    
        Dim ValidList As Variant
        ValidList = Array("123", "456") 'your list of valid entries
    
        'check if either str is in the ValidList OR matches the regex
        If (UBound(Filter(ValidList, str)) > -1) Or (allMatches.Count > 0) Then
            checkStr = True
        End If
    
    End Function
    
    如果有效条目列表在某个范围内,您可以将其替换为:

    ValidList = WorksheetFunction.Transpose(Worksheets("SheetName").Range("A1:A10").Value)
    

    我建议将返回值
    更改为布尔值
    ,然后根据有效列表项数组过滤
    str

    Function checkStr(ByVal str As String) As Boolean
    
        Dim objRegEx As Object, allMatches As Object
        Set objRegEx = CreateObject("VBScript.RegExp")
    
        With objRegEx
            .MultiLine = False
            .IgnoreCase = False
            .Global = True
            .Pattern = "^\d+(-\d+)?$"
        End With
    
        Set allMatches = objRegEx.Execute(str)
    
    
        Dim ValidList As Variant
        ValidList = Array("123", "456") 'your list of valid entries
    
        'check if either str is in the ValidList OR matches the regex
        If (UBound(Filter(ValidList, str)) > -1) Or (allMatches.Count > 0) Then
            checkStr = True
        End If
    
    End Function
    
    如果有效条目列表在某个范围内,您可以将其替换为:

    ValidList = WorksheetFunction.Transpose(Worksheets("SheetName").Range("A1:A10").Value)
    

    为什么函数返回字符串而不是布尔值?为什么函数返回字符串而不是布尔值?很抱歉,这可能是一个愚蠢的评论,但我对VBA不是很了解。复制时,出现一个错误,显示“编译错误:未定义子或函数”。我用以下代码调用函数:如果checkStr(Target.Value)=False,那么Target.Value=”“End If是模块或工作表中的
    函数checkStr
    ?尝试将其设置为
    公共功能
    。否则,该错误发生在哪一行?如果在某个范围内使用列表,则
    工作表(“SheetName”)
    中缺少一个
    s
    ,它必须是
    工作表
    而不是
    工作表
    (刚刚更正)。将其作为公共函数不会显示任何错误,但代码不起作用。它允许超出定义范围和模式的值。也更新了代码。@TryStudent很好,当我测试它时,它工作了。你能举个例子吗?您对
    str
    使用了什么值,对
    ValidList
    使用了什么值?将相同的代码复制粘贴到一个新文档中,它就工作了。谢谢你的帮助真的很感激:)如果这可能是一个愚蠢的评论,很抱歉,但我对VBA不是很了解。复制时,出现一个错误,显示“编译错误:未定义子或函数”。我用以下代码调用函数:如果checkStr(Target.Value)=False,那么Target.Value=”“End If是模块或工作表中的
    函数checkStr
    ?尝试将其设置为
    公共功能
    。否则,该错误发生在哪一行?如果在某个范围内使用列表,则
    工作表(“SheetName”)
    中缺少一个
    s
    ,它必须是
    工作表
    而不是
    工作表
    (刚刚更正)。将其作为公共函数不会显示任何错误,但代码不起作用。它允许超出定义范围和模式的值。也更新了代码。@TryStudent很好,当我测试它时,它工作了。你能举个例子吗?您对
    str
    使用了什么值,对
    ValidList
    使用了什么值?将相同的代码复制粘贴到一个新文档中,它就工作了。谢谢你的帮助真的很感激:)