0

我在 Excel 工作表上的以下代码。我正在使用 VBA 更改某些单元格的内容,以便为我的工作正确格式化它们。我们保留了损坏、托架位置和 VIN 的列表。这些列中的每一列都有自己特定的格式,其中 2 列我工作得很好。你们中的一些人可能会从我的另一篇关于正确格式化损坏代码的帖子中认出其中的一些代码。列是这样排序的

Bay Location | VIN | Damage Code(s)

对于 VIN,我们所做的只是大写字母。很简单,搞定了。损坏代码功能在我对其进行了一些更改以更好地满足我的需求后完美运行。如果没有我在这里收到的原始帮助,就无法做到这一点。这就是事情变得奇怪的地方,我的老板,看到我已经让它为损坏代码工作,让我让它自动格式化托架。我工作的海湾位置有几种可能性,但前面总是至少有 1 个字母,例如

  1. H-5
  2. H-125
  3. HH-50
  4. 7A-70
  5. FNCE-13

在英语中,我要做的是:输入无格式的bay,例如7a12,大写字母,用数字分割,并在两组之间添加破折号,瞧。

我有这个工作,甚至把它展示给我的老板。但后来我在代码中添加了大写的 VIN 列,我开始收到错误,突出显示该行

Set allMatches = RE1.Execute(strSource)

RE1.test(strSource) 运行良好,但现在尝试获取匹配项/子匹配项会神秘地引发错误。我最初使用This StackOverflow question中的文本来使其正常工作。我得到的错误类似于告诉我对象未设置。我知道代码目前一团糟,我不得不中途离开(我的函数可能有问题,不,直接从原始子函数运行时出现同样的错误)。

编辑:错误如下

运行时错误“91”对象变量或未设置块变量

再次强调

allMatches = RE.Execute(str)

任何帮助表示赞赏。

Private Sub Worksheet_Change(ByVal Target As Range)
    Dim KeyCells As Range
    Dim str As String, result As String
    Dim RE As Object
    Dim allMatches As Object

    ' The variable KeyCells contains the cells that will
    ' cause an alert when they are changed.
    Set KeyCells = Application.Union(Range("F3:F100"), Range("C3:C100"), Range("I3:I100"))
    Set RE = CreateObject("vbscript.regexp")

    If Not TypeName(Target.Value) = "Variant()" Then

        If Not Application.Intersect(KeyCells, Range(Target.Address)) _
            Is Nothing Then

            ' Display a message when one of the designated cells has been
            ' changed.
            ' Place your code here.
            str = ConvertString(Target)
            If (Not str = Target.Value And Not Target.Value = "") Then
                Target.Value = str
            End If

        End If

        ' Now we have to check the bays in order to auto format
        Set KeyCells = Application.Union(Range("A3:A100"), Range("D3:D100"), Range("G3:G100"))
        If Not Application.Intersect(KeyCells, Range(Target.Address)) _
            Is Nothing Then

            RE.Pattern = "([0-9]?[A-Z]{1,})\-?([0-9]{1,3})"
            RE.Global = True

            If Not Target.Value = "" And Not RE.test(Target.Value) Then
                    str = CStr(Target.Value)
                    RE.IgnoreCase = True
                    allMatches = RE.Execute(str)
                    MsgBox allMatches.Count

                    Target.Value = str
            End If

        End If

        Set KeyCells = Application.Union(Range("B3:B100"), Range("E3:E100"), Range("H3:H100"))

        If Not Application.Intersect(KeyCells, Range(Target.Address)) _
            Is Nothing Then

            RE.Pattern = "[a-z]?"
            RE.IgnoreCase = False

            If RE.test(Target.Value) Then
                Target.Value = UCase(Target.Value)
            End If

        End If
    End If
End Sub
Function FormatBay(str1 As Range) As String
    Dim result As String, strSource As String
    Dim allMatches As Object
    Dim RE1 As Object
    Set RE1 = CreateObject("vbscript.regexp")
    RE1.Pattern = "([0-9]?[A-Z]{1,})\-?([0-9]{1,3})"
    RE1.Global = True
    strSource = CStr(str1.Value)
    Set allMatches = RE1.Execute(strSource)
    result = "FF-12"
    If allMatches.Count <> 0 Then
        result = allMatches.Item(0)
    End If
    MsgBox result
    FormatBay = result
End Function
Function ConvertString(str1 As Range) As String
    Dim varStr As Variant
    Dim strSource As String, strResult As String
    Dim i As Integer

    For Each varStr In Split(Trim(str1.Value), " ")

            strSource = CStr(varStr)
        If InStr(strSource, ".") = 0 Then
            strResult = strResult & _
                Mid(strSource, 1, 2) & "." & _
                Mid(strSource, 3, 2) & "." & _
                Mid(strSource, 5, 1)
            If Len(strSource) > 5 Then
                strResult = strResult & "("
                For i = 6 To Len(strSource)
                    strResult = strResult & Mid(strSource, i, 1) & ","
                Next i
                strResult = Left(strResult, Len(strResult) - 1) & ")"
            End If
            strResult = strResult & " "
        Else
            strResult = strResult & strSource & " "
        End If
    Next

    If strResult = "" Then
        ConvertString = ""
    Else
        ConvertString = Left(strResult, Len(strResult) - 1)
    End If
End Function

编辑:这是我要工作的内容,我知道它有点长而且可能很冗长,但我只是在学习 VBA,所以当我学习更好的方法时,我会编辑这篇文章,希望以后能帮助别人.

Private Sub Worksheet_Change(ByVal Target As Range)
    Dim KeyCells As Range
    Dim str As String, result As String
    Dim RE As Object
    Dim allMatches As Object

    ' The variable KeyCells contains the cells that will
    ' cause an alert when they are changed.
    Set KeyCells = Application.Union(Range("F3:F100"), Range("C3:C100"), Range("I3:I100"))
    Set RE = CreateObject("vbscript.regexp")

    If Not TypeName(Target.Value) = "Variant()" Then


        ' Now we have to check the bays in order to auto format
        Set KeyCells = Application.Union(Range("A3:A100"), Range("D3:D100"), Range("G3:G100"))
        If Not Application.Intersect(KeyCells, Range(Target.Address)) _
            Is Nothing Then

            RE.Pattern = "([0-9]?[A-Z]{1,})\-?([0-9]{1,3})"
            RE.Global = True

            If Not Target.Value = "" And Not RE.test(Target.Value) Then
                    str = CStr(Target.Value)
                    str = FormatBay(str)

                    Target.Value = str
            End If

        End If

        Set KeyCells = Application.Union(Range("B3:B100"), Range("E3:E100"), Range("H3:H100"))

        If Not Application.Intersect(KeyCells, Range(Target.Address)) _
            Is Nothing Then

            RE.Pattern = "[a-z]?"
            RE.IgnoreCase = False

            If RE.test(Target.Value) Then
                Target.Value = UCase(Target.Value)
            End If

        End If

        Set KeyCells = Application.Union(Range("C3:C100"), Range("F3:F100"), Range("I3:I100"))

        If Not Application.Intersect(KeyCells, Range(Target.Address)) _
            Is Nothing Then

            ' Display a message when one of the designated cells has been
            ' changed.
            ' Place your code here.
            str = ConvertString(Target)
            If (Not str = Target.Value And Not Target.Value = "") Then
                Target.Value = str
            End If

        End If

    End If
End Sub
Function FormatBay(ByVal text As String) As String

    Dim result As String, bayLetter As String, bayNumber As String
    Dim length As Integer, i As Integer
    Dim allMatches As Object
    Dim RE As Object
    Set RE = CreateObject("vbscript.regexp")

    RE.Pattern = "([0-9]?[a-z]{1,})\-?([0-9]{1,3})"
    RE.Global = True
    RE.IgnoreCase = True

    Set allMatches = RE.Execute(text)

    If Not allMatches.Count = 0 Then
        bayLocation = allMatches.Item(0).submatches.Item(0)
        bayLocation = UCase(bayLocation)
        bayNumber = allMatches.Item(0).submatches.Item(1)
        length = Len(bayNumber)

        For i = 1 To (3 - length)
            bayNumber = "0" & bayNumber
        Next
        result = bayLocation & "-" & bayNumber
    End If

    FormatBay = result

End Function
Function ConvertString(str1 As Range) As String
    Dim varStr As Variant
    Dim strSource As String, strResult As String
    Dim i As Integer

    For Each varStr In Split(Trim(str1.Value), " ")

            strSource = CStr(varStr)
        If InStr(strSource, ".") = 0 And IsNumeric(strSource) Then
            strResult = strResult & _
                Mid(strSource, 1, 2) & "." & _
                Mid(strSource, 3, 2) & "." & _
                Mid(strSource, 5, 1)
            If Len(strSource) > 5 Then
                strResult = strResult & "("
                For i = 6 To Len(strSource)
                    strResult = strResult & Mid(strSource, i, 1) & ","
                Next i
                strResult = Left(strResult, Len(strResult) - 1) & ")"
            End If
            strResult = strResult & " "
        Else
            strResult = strResult & strSource & " "
        End If
    Next

    If strResult = "" Then
        ConvertString = ""
    Else
        ConvertString = Left(strResult, Len(strResult) - 1)
    End If
End Function
4

2 回答 2

1

allMatches是一个对象 (Type = MatchCollection) 变量。Set分配对象变量时应使用关键字。

Set allMatches = RE.Execute(str)

就您的代码当前而言,我认为它不会在不引发此错误的情况下工作,除非您或其他人无意中对代码进行了编辑并更改了分配此变量的方式。

希望这可以帮助!

于 2013-11-04T01:40:57.887 回答
0

首先,正则表达式[a-z]?总是匹配的。如果第一个字符Target.Value恰好是小写字母,则正则表达式将使用它。否则它将匹配第一个字符之前的空字符串。您正在测试是否存在小写字母,但是?通过将字母设为可选来破坏目的。

但我不明白你为什么需要做那个测试。无论如何,您要将所有字母都更改为大写,对吗?所以只是UCase字符串并完成它。或者等到转换完成UCase后再进行。

至于实际的转换,您的代码相当混乱,但我认为您正在做很多不必要的工作。如果您正在7a12单独处理字符串,这应该就足够了:

RE.Pattern = "^([0-9]?[A-Z]{1,})-?([0-9]{1,3})$"
RE.IgnoreCase = True
result = UCase(RE.Replace(source, "$1-$2"))

还是我错过了什么?

于 2013-11-04T02:10:19.473 回答