以下代码我在Excel工作表上。我正在使用VBA来改变某些单元格的内容,以便为我的工作正确格式化它们。我们会列出损坏,海湾位置和VIN。这些列中的每一列都有自己的特定格式,其中2个我工作正常。你们中的一些人可能会从另一篇关于正确格式化损坏代码的帖子中认出这些代码。列按此顺序排列
Bay Location | VIN | Damage Code(s)
对于VIN,我们所做的只是大写字母。很简单,完成了。在我改变它以更好地满足我的需要之后,损坏代码功能完美地工作。没有我在这里收到的原始帮助,就不可能做到这一点。在这里,事情变得奇怪,我的老板,看到我已经让这个为损坏代码工作,让我把它变成自动格式化托架。我工作的海湾位置有一些可能性,但前面至少有一个字母,如
在英语中,我想要做的是: 输入未格式化的托架,例如7a12,大写字母,用数字分割,并在两组之间添加一个破折号,然后瞧。
我有这个工作,甚至向我的老板展示。但后来我在代码中添加了大写VIN列,我开始收到错误,突出显示行
Set allMatches = RE1.Execute(strSource)
RE1.test(strSource)运行正常,但现在尝试抓取匹配/子匹配会神秘地抛出错误。我最初使用This StackOverflow question中的文字来使其正常工作。我得到的错误类似于它告诉我没有设置对象。我知道代码目前是乱七八糟的,我不得不离开中间工作(想想我的函数可能出现问题,nope,直接从原始子函数运行时出现同样的错误)。
编辑:错误如下
运行时错误'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
答案 0 :(得分:1)
allMatches
是一个对象(Type = MatchCollection
)变量。在分配对象变量时,应使用Set
关键字。
Set allMatches = RE.Execute(str)
正如您的代码目前所代表的那样,除非您或其他人对代码进行了无意的编辑并更改了此变量的分配方式,否则我认为它不会在没有引发此错误的情况下工作。
希望这有帮助!
答案 1 :(得分: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"))
或者我错过了什么?