如何在VBA中用多个字符分割字符串

3
在C#中,可以轻松地通过提供一个分隔符数组来拆分多个字符的字符串。我想知道如何在VBA中实现这一点的最佳方法。通常使用VBA.Split,但要在多个字符上进行拆分就需要深入结果并对元素进行子拆分。然后就必须重新定义数组等等,相当痛苦。 限制条件 请仅使用VBA响应。如果愿意,可以使用.NET集合类(是可创建和可调用的VBA对象)。如果愿意,可以使用JSON、XML作为列表分割段的容器。如果愿意,可以使用谦卑的VBA.Collection类,甚至是Scripting.Dictionary。如果愿意,可以使用自定义记录集。
我很清楚可以编写.NET程序集来调用.NET String.Split方法并使用COM接口将程序集暴露给VBA,但挑战在哪里呢?
2个回答

3
在我的尝试中,我在按空格分割之前用空格替换了所有其他字符。(所以我有点作弊。)
Private Function SplitByMoreThanOneChars(ByVal sLine As String)
    '*
    '* Brought to you by the Excel Development Platform Blog
    '* http://exceldevelopmentplatform.blogspot.com/2018/11/
    '*
    '* Don't get excited, this splits by spaces only
    '* we fake splitting by multiple characters by replacing those characters
    '* with spaces 
    '*
    Dim vChars2 As Variant
    vChars2 = Array(" ", "<", ">", "[", "]", "(", ")", ";")

    Dim sLine2 As String
    sLine2 = sLine

    Dim lCharLoop As Long
    For lCharLoop = LBound(vChars2) To UBound(vChars2)
        Debug.Assert Len(vChars2(lCharLoop)) = 1
        sLine2 = VBA.Replace(sLine2, vChars2(lCharLoop), " ")
    Next

    SplitByMoreThanOneChars = VBA.Split(sLine2)


End Function

2
更加通用的方法是将“split”数组中的所有字符替换为第一个字符,然后在第一个字符处进行分割... - Tim Williams

3

使用正则表达式应该很容易完成。如果匹配传递的分隔符字符的否定形式,则匹配项将成为输出数组的成员。这样做的好处是,输出数组只需要调整一次大小,因为您可以获得RegExp返回的匹配计数。构建模式相当简单-它可归纳为类似[^abc]+的东西,其中'a','b'和'c'是要分割的字符。准备表达式需要做的仅仅是转义在正则表达式中具有特殊意义的一些字符(我可能会忘记某些字符):

Private Function BuildRegexPattern(ByVal inputString As String) As String
    Dim escapeTargets() As String
    escapeTargets = VBA.Split("- ^ \ ]")

    Dim returnValue As String
    returnValue = inputString

    Dim idx As Long
    For idx = LBound(escapeTargets) To UBound(escapeTargets)
        returnValue = Replace$(returnValue, escapeTargets(idx), "\" & escapeTargets(idx))
    Next
    BuildRegexPattern = "[^" & returnValue & "]+"
End Function

一旦你拥有了模式,只需要调整数组大小并迭代匹配项来分配它们(以及一些其他特殊情况处理等):

Public Function MultiSplit(ByVal toSplit As String, Optional ByVal delimiters As String = " ") As String()
    Dim returnValue() As String

    If toSplit = vbNullString Then
        returnValue = VBA.Split(vbNullString)
    Else
        With New RegExp
            .Pattern = BuildRegexPattern(IIf(delimiters = vbNullString, " ", delimiters))
            .MultiLine = True
            .Global = True
            If Not .Test(toSplit) Then
                'Only delimiters.
                ReDim returnValue(Len(toSplit) - 1)
            Else
                Dim matches As Object
                Set matches = .Execute(toSplit)
                ReDim returnValue(matches.Count - 1)
                Dim idx As Long
                For idx = LBound(returnValue) To UBound(returnValue)
                    returnValue(idx) = matches(idx)
                Next
            End If
        End With
    End If

    MultiSplit = returnValue
End Function

1
很棒,这样就涵盖了正则表达式的方面。 - S Meaden
非常好 +。VBA.Split(vbNullString) 产生 String(0 to -1),多么奇怪! - QHarr

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接