簡體   English   中英

如何在vba excel中用多個分隔符分割字符串?

[英]How to split a string with multiple delimiters in vba excel?

我想使用 Excel VBA 拆分帶有多個分隔符的字符串。 其中一個字符串是:

d1-d2 d3 d4  

我們有一個破折號和一個空格作為兩個分隔符。 我嘗試了split功能,但它只使用一個分隔符。

您可以先對字符串進行Replace ,然后再進行拆分:

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

前面的答案很好,但是如果字符串中有要拆分的背靠背字符,則會給您帶來麻煩,例如拆分“您好,先生!今天好嗎?” 所有標點符號和空格。 在這種情況下,您將在 Hello 和 Sir 之間得到一個空白字符串。

為了處理這種情況,Chip Pearson 提供了一個很棒的 VBA 函數供使用: http : //www.cpearson.com/excel/splitondelimiters.aspx

用幾個不同的分隔符分割; 列出數組中的分隔符,用 for 循環替換它們,然后拆分:

' New delimiter
tDelimNew = "myDelimiter"

' Replace each possible delimiter
For Each tDelimOld In Array(";", " ", ".", "<==", ":", vbCr)
    tString = Replace(tString, tDelimOld, tDelimNew)
Next tDelimOld

' Remove duplicate delimiters
tString = Replace(tString, tDelimNew & tDelimNew, tDelimNew)

' Split ;)
tResult = Split(tString , tDelimNew)

不允許評論(還),但使用 TRIM 消除雙空格的建議尚不完全清楚。 VBA 中的 TRIM 函數只刪除前導和尾隨空格。 它不會觸及字符串內的雙空格。 為此,您必須使用工作表功能。

我要補充一點,我快速瀏覽了 Chip Pearson 的答案,並認為它可以在性能方面有所改進,所以我寫了自己的答案,它似乎快了 40%(隨意測試自己)。 它更快(每個周期1.0E-51.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

在這種情況下你可以做

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM