Это должно быть довольно легко сделать с помощью регулярного выражения. Если вы сопоставляете отрицание пропущенных символов для разделения, совпадения будут членами выходного массива. Преимущество этого состоит в том, что размер выходного массива нужно только один раз, потому что вы можете получить количество совпадений, возвращаемых 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