Comment diviser une chaîne de caractères avec plusieurs délimiteurs dans VBA excel?

je veux partager une chaîne avec plusieurs délimiteurs en utilisant Excel VBA. L'une des chaînes est:

d1-d2 d3 d4  

nous avons un tiret et un espace comme deux délimiteurs. J'ai essayé le split fonction mais il ne le fait qu'avec un délimiteur.

13
demandé sur Cœur 2011-10-07 01:09:58

6 réponses

vous pourriez d'abord faire un REPLACE sur la chaîne en premier et ensuite faire la split:

newString = Replace(origString, "-", " ")
newArray = SPlit(newString, " ")
27
répondu PaulStock 2011-10-06 21:15:39

la réponse précédente est bonne, mais elle vous causera des problèmes s'il y a des caractères dos à dos à partager sur ceux qui sont dans la chaîne, comme Partager "Hello, Sir! Comment faites-vous, aujourd'hui?"sur toutes les ponctuations et les espaces. Dans ce cas, vous obtiendriez une corde blanche entre bonjour et Monsieur.

pour gérer ce scénario Chip Pearson fournit une grande fonction VBA à utiliser: http://www.cpearson.com/excel/splitondelimiters.aspx

3
répondu Michael Merchant 2018-05-08 21:48:18

pas autorisé à commenter (encore) mais la suggestion d'utiliser TRIM pour éliminer un double espace n'est pas entièrement claire. La fonction TRIM dans VBA supprime seulement les espaces de tête et de fuite. Il ne touche pas les espaces doubles à l'intérieur d'une corde. Vous devez utiliser la fonction de feuille de calcul.

1
répondu Reged 2016-06-02 08:54:12

pour séparer avec plusieurs délimiteurs différents; listez les délimiteurs dans un tableau, remplacez - les par un pour boucle, puis séparez :

For Each tSep In Array(";", " ", ".", "<==", ":", vbCr)
    val1 = Replace(val1, tSép, "°")
Next tSep
tab1 = Split(val1, "°")
1
répondu rejdrouin 2017-12-22 19:02:18

dans ce cas, vous pourriez faire

    newString = Replace(origString, "-", " ")
    newString2 = replace(newstring, "  " , " ")
    newArray = SPlit(newString, " ")
0
répondu Dave Odle 2016-02-08 16:45:05

j'ajouterai que j'ai jeté un coup d'oeil à la réponse de Chip Pearson, et j'ai pensé qu'elle pourrait être améliorée un peu en termes de performance, donc j'ai écrit la mienne qui semble être environ 40% plus rapide (n'hésitez pas à vous tester). C'est plus rapide (1.0E-5 et 1.7E-5 secondes par cycle) parce qu'il utilise des tableaux d'octets plutôt que des caractères réels pour comparer les valeurs. Voici la fonction qui renvoie une chaîne de caractères comme celle de 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

voici le journal des essais (le sien est SplitMultiDelims, le mien is 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

courir dans les deux sens pour éviter les handicaps de mémoire d'écriture

Code Test ci-dessous utilise Timer donc pas trop précis, mais assez bon pour montrer la différence

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
0
répondu Greedo 2017-06-08 09:46:12