我有一个非常多余的旧代码,我在第一次发现并决定学习vba时创建了这个代码(而且我有很长的路要走)。我正在使用此代码循环遍历包含用逗号分隔的多个值的单元格。但是,有些情况下我不能简单地使用诸如Split(string,",")
函数之类的东西,因为某些值在该值中有逗号(示例值: [blah blah,so blah blah] )。在存在这些括号的情况下(它们围绕着其中包含逗号的每个值)我设计了相当啰嗦的方法,这是我的旧方法,正确地将值拆分,将它们转储到数组中,然后继续我的其他任务。但是,现在我决定重新审视代码并修复准确性。这是一些背景知识。
可以在一个单元格中找到的示例数据:
请注意:这是供应商发送给我们的数据,我们无法控制他们输入的内容或输入方式。这是一个简单的例子,展示了在某些情况下通常如何提供数据的要点
Available on 2 sides: Silkscreen,[full: color, covers entire face],Pad Print: One color,[heat transfer, may bleed]
值为:
我在寻找什么:
我正在寻找一种更有效,更简单的方法,能够正确地分割值(同时保留包含它们的值的括号)。
我相信我已设法使用以下代码创建一个更高效,更紧凑的方法来处理不包含括号的实例
新规范(在建): 我有问题,不知道如何有效和准确地用括号分割单元格
Sub Test()
Dim rngXid As Range, RegularColons As New Collection, UpchargeColons As New Collection, additionals As Range, upcharges As Range, Colon, UpchargeColon
Dim Values() As String, endRange As Long, xidMap As Object, xid As String, NumberofValues As Integer
endRange = ActiveSheet.Range("A" & Rows.Count).End(xlUp).Row
Set xidMap = getXidMap(ActiveSheet.Range("A2:A" & UsedRange.Rows.Count)) 'Map products for quicker navigation
Set additionals = ActiveSheet.Range("AJ:AK"): Set upcharges = ActiveSheet.Range("CS:CT")
Set RegularColons = FindAllMatches(additionals, ":") 'This returns all instances/cells that contain a colon in the specified columns
If Not RegularColons Is Nothing Then
For Each Colon In RegularColons
xid = ActiveSheet.Range("A" & Colon.Row).Value
If InStr(1, Colon.Value, "[") = 0 Then 'If no brackets then simply split
Values = Split(Trim(Colon.Value), ",")
Else
'This is where I'm at a lose for a more effective method
'-----------Populate Values array with Colon.Value while watching out for brackets--------
End If
Set rngXid = xidMap(xid).EntireRow.Columns(upcharges) 'set to this specific product
For ColorLocation = LBound(Values) To UBound(Values) 'cycle through each value in Values array
If Not InStr(1, Values(ColorLocation), ":") = 0 Then 'Only proceed if the value has a colon
Set UpchargeColons = FindAllMatches(rngXid, Values(ColorLocation)) 'Searching other columns for this value
If Not UpchargeColons Is Nothing Then
For Each UpchargeColon In UpchargeColons 'If found in other columns proceed to replace colon
UpchargeColon.Value = Replace(UpchargeColon.Value, ":", " ")
Log UpchargeColon.Range, "Removed Colon from Additional Color/Location Upcharge", "Corrected" 'This is a custom sub of mine to record the change
Next UpchargeColon
End If
Values(ColorLocation) = Replace(Values(ColorLocation), ":", " ")
End If
Next ColorLocation
Log Colon.Range, "Removed Colon(s) from Additional Color/Location Value(s)", "Corrected"
Next Colon
End If
End Sub
我一直在寻找可能的方法来做到这一点而且一直坚持的是Regex
,我承认我完全没有经验,尽管我之前已经听说过。所以,我尝试使用像this这样的网站,当然还有msdn documentation来阅读它。我在尝试更多地了解这种方法时的观察/想法是:
所以,我的问题是:
在包含括号的单元格中准确分割值的最有效方法是什么?
答案 0 :(得分:3)
还有其他方法,但这个正则表达式看起来非常快:
(\[[^\]]+\]|[^,]+),?
说明:
\[
和\]
是[
和]
的转义版本
基本上,它正在寻找\[
,获取所有非括号[^\]]
,然后是\]
。否则|
,它将获得所有非逗号[^,]
。周围的()
使其成为捕获组。 ,?
表示可能有也可能没有逗号。
答案 1 :(得分:3)
一种方法是使用括号中的逗号并将其替换为 Chr(184)。这些小家伙看起来很像逗号。
更换括号内的逗号后,您可以使用普通的 Split()以下是一些代码来进行替换:
Sub parser()
Dim s As String, s1 As String, s2 As String, pseudo As String
Dim switch As Boolean, temp As String, CH As String
pseudo = Chr(184)
s1 = "["
s2 = "]"
s = [A1]
switch = False
temp = ""
For i = 1 To Len(s)
CH = Mid(s, i, 1)
If CH = s1 Or CH = s2 Then switch = Not switch
If switch Then CH = Replace(CH, ",", pseudo)
temp = temp & CH
Next i
Range("A2").Value = temp
MsgBox s & vbCrLf & temp
End Sub
答案 2 :(得分:2)
正则表达式(又名“正则表达式”)确实很吓人,但它们也是一个强大的工具,如果你添加对 Microsoft VBScript正则表达式5.5 的引用,VBA支持它们库。
有了它,你可以创建一个RegExp
对象,它会给你一个MatchCollection
,它是一个Match
个对象的集合。
以下是如何使用它们:
Sub Test()
Const value As String = _
"Available on 2 sides: Silkscreen,[full: color, covers entire face],Pad Print: One color,[heat transfer, may bleed]"
Const pattern As String = _
"(\[[^\]]+\]|[^,]+)"
Dim regex As New RegExp
regex.Global = True
regex.pattern = pattern
Dim matches As MatchCollection
Set matches = regex.Execute(value)
Dim m As Match
For Each m In matches
Debug.Print Trim(m.value) 'value will preserve any leading/trailing spaces
Next
End Sub
请注意,pattern
中的(\[[^\]]+\]|[^,]+)
几乎与Laurel's answer相同:
Available on 2 sides: Silkscreen
[full: color, covers entire face]
Pad Print: One color
[heat transfer, may bleed]
通过不指定您想要匹配逗号,您不匹配它(无论它是否存在) - 因此,上面的代码输出:
MatchCollection
如果需要,可以轻松迭代{{1}}以填充数组。
答案 3 :(得分:1)
Document