如何在vba excel中拆分包含多个分隔符的字符串?

时间:2011-10-06 21:09:58

标签: excel vba

我想使用Excel VBA拆分包含多个分隔符的字符串。其中一个字符串是:

d1-d2 d3 d4  

我们有一个破折号和一个空格作为两个分隔符。我尝试了split函数,但它只使用一个分隔符。

6 个答案:

答案 0 :(得分:31)

您可以先在字符串上执行Replace,然后再进行拆分:

newString = Replace(origString, "-", " ")
newArray = Split(newString, " ")

答案 1 :(得分:3)

之前的答案是好的,但是如果在字符串中有要分割的背靠背字符会导致你遇到麻烦,例如拆分“你好,先生!你今天怎么样?”在所有标点符号和空格上。在这种情况下,你会在Hello和Sir之间得到一个空白字符串。

为了处理这种情况,Chip Pearson提供了一个很棒的VBA功能: http://www.cpearson.com/excel/splitondelimiters.aspx

答案 2 :(得分:2)

与几个不同的分隔符分开;列出数组中的分隔符,用for循环替换它们,然后拆分:

For Each tSep In Array(";", " ", ".", "<==", ":", vbCr)
    val1 = Replace(val1, tSép, "°")
Next tSep
tab1 = Split(val1, "°")

答案 3 :(得分:1)

不允许评论(但)但是建议使用TRIM消除双倍空间并不完全清楚。 VBA中的TRIM功能仅删除前导和尾随空格。它不会触及字符串中的双重空格。你必须使用工作表函数。

答案 4 :(得分:0)

在这种情况下你可以做

    newString = Replace(origString, "-", " ")
    newString2 = replace(newstring, "  " , " ")
    newArray = SPlit(newString, " ")

答案 5 :(得分:0)

我要补充一点,我快速浏览了Chip Pearson的答案,并认为它可以在性能方面稍微提高一点,所以我写了自己的答案,其速度提高了约40%(随意测试自己) )。它更快(每个周期1.0E-5 vs 1.7E-5秒),因为它使用字节数组而不是实际字符来比较值。这是返回像Chip Pearson的字符串数组的函数:

Function SplitMultiDelims2(Text As String, DelimChars As String) As String()
'''
'Function to split a string at multiple charachters
'Use like SplitMultiDelims2("This:is-a,test string", ":-,")
'Returns an array, in that example SplitMultiDelims2("This:is-a,test string", ":-,")(4) would be "test string"
'''
Dim bytes() As Byte
Dim delims() As Byte
Dim i As Long, aub As Long, ub As Long
Dim stack As String
Dim t() As String
Dim tLen As Long
tLen = Len(Text)
If tLen = 0 Then
    Exit Function
End If
ReDim t(1 To tLen) 'oversize array to avoid Redim Preserve too often
bytes = StrConv(Text, vbFromUnicode)
delims = StrConv(DelimChars, vbFromUnicode)
ub = UBound(bytes)
For i = 0 To ub
    If Contains(delims, bytes(i)) Then
        aub = aub + 1
        t(aub) = stack
        stack = ""
    Else
        stack = stack & Chr(bytes(i))
    End If
Next i
t(aub + 1) = stack
ReDim Preserve t(1 To aub + 1) 'Works marginally faster if you delete this line,
    'however it returns an oversized array (which is a problem if you use UBOUND of the result, 
    'but fine if you are just looking up an indexed value like the 5th string)
SplitMultiDelims2 = t
End Function

'and a 2nd function called by the first one
Function Contains(arr, v As Byte) As Boolean 'checks if Byte v is contained in Byte array arr
Dim rv As Boolean, lb As Long, ub As Long, i As Long
    lb = LBound(arr)
    ub = UBound(arr)
    For i = lb To ub
        If arr(i) = v Then
            rv = True
            Exit For
        End If
    Next i
    Contains = rv
End Function

这是测试日志(他的是SplitMultiDelims,我的是SplitMultiDelims2)

> SplitMultiDelims: 1.76105267188204E-05s per cycle 'this is the important figure
> i = 568064 iterations in 10.00390625 seconds
>Test completed: 08/06/2017 10:23:22
> SplitMultiDelims2: 1.05756701906142E-05s per cycle
>i = 947044 iterations in 10.015625 seconds
>Test completed: 08/06/2017 10:23:32
> SplitMultiDelims2: 1.04176859354441E-05s per cycle
>i = 960656 iterations in 10.0078125 seconds
>Test completed: 08/06/2017 10:23:54
> SplitMultiDelims: 1.76228941673255E-05s per cycle
>i = 567887 iterations in 10.0078125 seconds
>Test completed: 08/06/2017 10:24:04

双向奔跑以避免记忆写作障碍

下面的测试代码使用Timer,因此不会过于精确,但足以证明差异

Sub testSplit()
Dim t As Double, dt As Double
Dim s As String
Dim i As Long
t = Timer: i = 0: dt = 0: s = ""
Do Until dt > 10 'loop for 10 seconds
    s = SplitMultiDelims("This:is-a,test string", ":-,")(1)
    dt = Timer - t
    i = i + 1
Loop
Debug.Print "SplitMultiDelims: " & dt / i & "s per cycle" & vbCrLf & "i = " & i; " iterations in " & dt; " seconds" & vbCrLf & "Test completed: " & Now
t = Timer: i = 0: dt = 0: s = ""
Do Until dt > 10 'loop for 10 seconds
    s = SplitMultiDelims2("This:is-a,test string", ":-,")(1)
    dt = Timer - t
    i = i + 1
Loop
Debug.Print "SplitMultiDelims2: " & dt / i & "s per cycle" & vbCrLf & "i = " & i; " iterations in " & dt; " seconds" & vbCrLf & "Test completed: " & Now
End Sub