【问题标题】:Regular expression to validate US and Canada zipcodes - Runtime Error 438 excel验证美国和加拿大邮政编码的正则表达式 - 运行时错误 438 excel
【发布时间】:2019-05-23 19:45:51
【问题描述】:

我编写此代码是为了帮助验证我们供应商表单中的邮政编码单元格。我希望它在移动到下一个单元格时进行验证。我收到运行时 438 错误:当我尝试移动到下一个单元格时,对象不支持此属性或方法。我需要这个来验证所有美国和加拿大的邮政编码(正在使用英语)。

我已尝试通过数据验证来执行此操作,我可以同时拥有美国或加拿大,但不能同时拥有两者。

Private Sub worksheet_selectionchange(ByVal target As Range)
    If Selection.Count = 1 Then
        'Erm, nothing to do here....
    ElseIf Not Intersect(target, Range("B39,B50")) Is Nothing Then
        Exit Sub
    End If

    Dim searchRange     As Excel.Range
    Dim cell            As Variant
    Dim RegEx           As Object

    Set RegEx = CreateObject("VBScript.RegExp")

    With RegEx
        .Pattern = "^(\d{5}(-\d{4})?|[A-CEGHJ-NPRSTVXY]\d[A-CEGHJ-NPRSTV-Z] ?\d[A-CEGHJ-NPRSTV-Z]\d)$"
        .Global = True
        .MultiLine = True
    End With

    Set searchRange = ActiveSheet.Range("B39,B50")
    For Each cell In searchRange.Cells
       If RegEx.IsMatch(subjectString, "^(\d{5}(-\d{4})?|[A-CEGHJ-NPRSTVXY]\d[A-CEGHJ-NPRSTV-Z] ?\d[A-CEGHJ-NPRSTV-Z]\d)$") Then
            MsgBox ("Valid ZIP code")
        Else
            MsgBox ("Invalid ZIP code")
        End If
    Next cell
    Set searchRange = Nothing
    Set RegEx = Nothing

End Sub

调试行是

  If RegEx.IsMatch(subjectString, "^(\d{5}(-\d{4})?|[A-CEGHJ-NPRSTVXY]\d[A-CEGHJ-NPRSTV-Z] ?\d[A-CEGHJ-NPRSTV-Z]\d)$") Then

我不在乎我是使用数据验证还是 VBA,我只需要准备好一些东西来验证这一点。请在您的回复中详细说明我对 VBA 和正则表达式仍然相当“绿色”。

【问题讨论】:

  • 那个缩进伤害了我的大脑:-(
  • 在哪里声明 subjectString ?它没有任何价值,因此没有什么可匹配的......我想这就是你收到错误的原因。使用Option Explicit 有很大帮助。
  • 我可能错了,因为我更喜欢在 vba 和字符串函数中使用 Like 运算符,所以我对正则表达式不太熟悉,但我找不到任何参考官方文档中VBA中的IsMatch方法。我只在 /dotnet/ 文档中找到IsMatch,虽然它与 VBA 有相似之处
  • @Rawrplus 我也不是 RegEx 的忠实粉丝,但看起来你是对的...Microsoft Beefs Up VBScript with Regular Expressions
  • 所以,我使用了这个link,它没有调出主题字符串。我很乐意采取另一种不使用正则表达式的方式来编写它,我只是无法找到任何东西可以在同一个单元格中同时进行这两种操作。我不确定Option explicit 的评论。

标签: regex excel vba zipcode


【解决方案1】:

应该可以(假设模式没问题):

Private Sub worksheet_selectionchange(ByVal target As Range)

    Static RegEx As Object '<<
    Dim searchRange As Range

    Set searchRange = Application.Intersect(Target, Me.Range("B39, B50"))
    If searchRange Is Nothing then Exit Sub

    'see if we need to set up the regexp object
    If RegEx Is Nothing Then
        Set RegEx = CreateObject("VBScript.RegExp")
        With RegEx
            .Pattern = "^(\d{5}(-\d{4})?|[A-CEGHJ-NPRSTVXY]\d" & _
                       "[A-CEGHJ-NPRSTV-Z] ?\d[A-CEGHJ-NPRSTV-Z]\d)$"
            .Global = True
            .MultiLine = True
        End With
    End If

    For Each cell In searchRange.Cells
        MsgBox IIf(RegEx.Test(cell.Value), "Valid", "Invalid") & " ZIP code"
    Next cell

End Sub

编辑:如果您想在 Worksheet_Change 中做两件事,那么您可以将所有代码合并到一个事件处理程序中,或者执行以下操作:

Private Sub worksheet_change(ByVal target As Range)
    HandleFirstThing Target
    DoSomethingElse Target
End Sub

Sub HandleFirstThing(Target As Range)
   'first thing to handle
End Sub

Sub DoSomethingElse(Target As Range)
   'next thing to handle
End Sub

【讨论】:

  • 好的,这是一种工作,当我选择单元格时它会弹出消息框,而不是当我从单元格继续前进时
  • Selection_change 在选择新单元格/范围时触发:也许您需要的事件是 Worksheet_Change
  • 如果我已经将某些东西定义为 worksheet_change ,那么无论如何都要这样做而不会得到一个不明确的名称?
  • 没有理由不能将这两者结合到一个程序中。
  • 我喜欢你给我的另一个挑战。我想如果我在调试这个时遇到问题,我将不得不提交另一个帖子?哈哈还是像Exit Sub 然后运行第二个代码然后end sub 一样简单
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-07-06
  • 1970-01-01
  • 2012-06-24
  • 2011-05-05
  • 1970-01-01
  • 2019-02-25
  • 1970-01-01
相关资源
最近更新 更多