Как разбить строку в VBA более чем на один символ - PullRequest
0 голосов
/ 04 ноября 2018

В C # можно легко разбить разделенную строку более чем на один символ, каждый предоставляет массив разделенных символов. Мне было интересно, как лучше всего добиться этого в VBA. Обычно я использую VBA.Split, но для разбиения более чем на один символ требуется детализация результатов и разбиение элементов. Затем нужно изменить размеры массивов и т. Д. Довольно больно.

контрсилы

Только ответы VBA, пожалуйста. Вы можете использовать классы коллекций .NET, если хотите ( да, они могут создаваться и вызываться в VBA ). Вы можете использовать JSON, XML как сосуды для списка разделенных сегментов, если хотите. При желании вы можете использовать скромный класс VBA.Collection или даже Scripting.Dictionary. Вы можете использовать даже сфабрикованный набор записей, если хотите.

Я прекрасно знаю, что можно написать ассемблер .NET для вызова метода .NET String.Split и предоставить сборку VBA с интерфейсами COM, но где проблема в этом.

Ответы [ 2 ]

0 голосов
/ 05 ноября 2018

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

В моей попытке я заменяю все остальные символы пробелом перед разделением на пробел. (Так что я немного обманываю.)

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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...