用分隔符分割string的最有效的方法,同时使用excel vba忽略所述分隔符的某些实例

我有一个非常冗余的旧代码,我创build时,我第一次发现,并决定学习vba(和男人我走了很长的路)。 我正在使用此代码来循环通过包含多个用逗号分隔的值的单元格。 但是,有些情况下,我不能简单地使用诸如Split(string,",")函数之类的东西,因为某些值在该值内有逗号(示例值: [blah blah,so blah blah] )。 在存在这些括号的情况下(它们围绕着每个值都有一个逗号),我devise了一个相当冗长的方法,这是我的老方法来正确地分割值,把它们倒入一个数组,然后继续我的其他任务。 但是,现在我已经决定重新审视这些代码并修正了这个问题的准确性。 这是一些背景。

示例可以在一个单元格中find的数据:
请注意:这是供应商发给我们的数据,我们无法控制他们input的内容或input内容。 这是一个简单的例子,以显示在某些情况下通常提供数据的要点

 Available on 2 sides: Silkscreen,[full: color, covers entire face],Pad Print: One color,[heat transfer, may bleed] 

价值观是:

  • 可用于两面:丝网印刷
  • [全部:颜色,覆盖整个脸]
  • 移印:一种颜色
  • [传热,可能stream血]

我在找什么:
我正在寻找一个更有效和更简单的方法来正确地分割值(同时保留有它们的值的括号)。

我相信我已经设法创build一个更有效率和紧凑的方法来处理不包含使用下面的代码括号的实例

新的代码(正在build设中):我不知道如何有效和准确地分割与括号的单元格的问题

 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 ,虽然我以前听说过,但我完全没有经验。 所以,我尝试使用这样的网站,当然还有msdn文档 。 我想了解更多关于这种方法的观察/想法是:

  1. 这绝对是非常复杂和令人恐惧的。 所以我必须避免爬到一个angular落,假设胎位,然后睁大眼睛。
  2. 我似乎无法find任何能够提示我如何将该function与我需要适当地分割string的东西相提并论,至less据我所知。 但是,我可能会被所有看似随机的符号序列所淹没

所以,我的问题是:
什么是最有效的方法来精确分割包含括号的单元格中的值?

正则expression式(又名“正则expression式”)确实是令人恐惧的,但它们也是一个强大的工具,而VBA支持它们,如果您添加对Microsoft VBScript正则expression式5.5库的引用。

有了它,你可以创build一个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的答案中非常多:

 (\[[^\]]+\]|[^,]+) 

通过不指定你想匹配一个逗号,你不匹配它(无论是否存在) – 因此,上面的代码输出这个:

 Available on 2 sides: Silkscreen [full: color, covers entire face] Pad Print: One color [heat transfer, may bleed] 

如果需要,可以轻松地迭代MatchCollection来填充数组。

还有其他的方法,但是这个正则expression式似乎相当快:

(\[[^\]]+\]|[^,]+),?

说明:

\[\]\[\]的转义版本

本质上,它正在寻找一个\[ ,所有非括号[^\]] ,然后\] 。 否则| ,它会得到所有的非逗号[^,] 。 周围()使它成为一个捕获组。 ,? 意味着可能有也可能没有逗号。

一种方法是采用括号内的逗号replace为Chr(184) 。 这些小家伙看起来很像逗号。

一旦括号逗号被replace,你可以使用正常的Split()这里有一些代码来做replace:

 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 

在这里输入图像说明

 Function Splitter(s) Dim p As Long, b As Long, l As String Dim c As Long, s2 As String, arr, n If InStr(s, "[") = 0 Then arr = Split(s, ",") Else c = 0 For p = 1 To Len(s) l = Mid(s, p, 1) If l = "," And c = 0 Then Mid(s, p, 1) = vbNull Else If l = "[" Then c = c + 1 If l = "]" Then c = c - 1 End If Next p arr = Split(s, vbNull) End If Splitter = arr End Function