Преобразование строк Excel VBA со свойствами Math - PullRequest
0 голосов
/ 01 сентября 2018

У меня есть любопытство, которое пробудило во мне интерес и поставило меня в тупик. У меня есть ситуация, когда у меня есть куча строк, некоторые с математическими символами, а некоторые просто символы. Некоторые из этих строк очень длинные, некоторые нет, однако я хотел бы добавить Chr (10) после полной строки любой строки, имеющей символ Math (в частности, +, -), а затем продолжить чтение строки для следующий математический символ и вставив перед ним Chr (10).

Конечный результат должен выглядеть примерно так:

10+20+30+40 50+60+70+80 123a 123 123b 345 123c 123 123d 123 90+100+110+120 123 123 231 123

Converts to: 

10+20+30+40  
50+60+70+80 
123a 123 123b 345 123c 123 123d 123 
90+100+110+120 
123 123 231 123

Если в уравнениях нет пробелов, у простых букв (может быть комбинация цифр и букв) могут быть пробелы, но они разделяются при обнаружении символа математики.

Я искал в Интернете некоторые подсказки, и я думаю, что очень близок к тому, чтобы выяснить это. Кажется, ответом является функция split, merge или Right (), Left (), а затем Len ().

 If Len(SearchString) = "+" Or Len(SearchString) = "-" Then
    SearchString = Left(SearchString, Chr(10))
 End If

Это, однако, не работает. Возможно, я недостаточно хорошо понимаю функции Len, Left и Right, но я вполне уверен, что SearchString - правильный курс действий. Также стоит отметить, что оператор If / End If, который я предоставил, работает, он не возвращает никаких ошибок, но не делает то, что я хочу.

Ответы [ 4 ]

0 голосов
/ 02 сентября 2018

InStr и InStrRev должны иметь возможность обрабатывать разбиения.

Option Explicit    

Function splitString(str As String)

    Dim a As Long, b As Long

    a = InStr(1, str, Chr(32))
    b = InStr(1, str, Chr(43))

    Do While a > 0 And b > 0

        If b > a Then
            a = InStrRev(str, Chr(32), b)
        End If

        Mid(str, a, 1) = Chr(10)

        b = InStr(a, str, Chr(43))
        a = InStr(a, str, Chr(32))

    Loop

    splitString = str

End Function

enter image description here

0 голосов
/ 01 сентября 2018

Так что это не идеально, но использует регулярное выражение для взлома.

Option Explicit
Public Sub TEST()
    Dim tests(), i As Long
    tests = Array("10+20+30+40 50+60+70+80 123a 123 123b 345 123c 123 123d 123 90+100+110+120 123 123 231 123")
    For i = LBound(tests) To UBound(tests)
        Debug.Print ReplaceString(tests(i))
    Next
End Sub

Public Function ReplaceString(ByVal inputString As String) As String
Dim matches As Object, match As Object
  With CreateObject("VBScript.RegExp")
            .Global = True
            .MultiLine = True
            .Pattern = "(\w+\+|\-)+(\w)+"
            If .TEST(inputString) Then
              Set matches = .Execute(inputString)
              For Each match In matches
                  inputString = Replace$(Replace$(inputString, Chr$(32) & match, Chr$(10) & match), match & Chr$(32), match & Chr$(10))
              Next
              ReplaceString = Trim$(inputString)
            Else
              ReplaceString = inputString
            End If
  End With
End Function

1-я группа захвата (\w+\+|\-)+

\+ Квантификатор - соответствует от одного до неограниченного количества раз, столько раз, сколько возможно, возвращая при необходимости (жадный)

1-ая альтернатива \w+\+

\w+ соответствует любому символу слова (равен [a-zA-Z0-9_])

\+ Квантификатор - сопоставляет от одного до неограниченного числа раз, столько раз, сколько возможно, возвращая при необходимости (жадный)

\+ соответствует символу + буквально (с учетом регистра)

2-й вариант \- \- соответствует символу - буквально (с учетом регистра)

2-я группа захвата (\w)+

\+ Квантификатор - сопоставляет от одного до неограниченного количества раз, столько раз, сколько возможно, возвращая при необходимости (жадный)

\w соответствует любому символу слова (равен [a-zA-Z0-9_])

Попробуйте здесь

Спасибо @RonRosenfeld за помощь в улучшении моего регулярного выражения.

0 голосов
/ 01 сентября 2018

Вот еще один способ использования регулярных выражений. Я использую .Replace метод

Option Explicit
Sub splitter()
    Dim S As String, RE As Object
    Const spat As String = "((?:(?:\w+[+-])+)+\w+)(?=\s|$)|(?:^|\s)((?:\w+\s+)+\w+)(?=\s|$)"
    Dim sRes As Variant

S = "10+20+30+40 50+60+70+80 123a 123 123b 345 123c 123 123d 123 90+100+110+120 123 123 231 123"

Set RE = CreateObject("vbscript.regexp")
With RE
    .Global = True
    .MultiLine = True
    .Pattern = spat
    sRes = .Replace(S, vbLf & "$1$2")
    MsgBox sRes
End With

End Sub

Как применить это, будет зависеть от ваших настроек данных; просматривая исходные данные и выплевывая результаты куда-то.

Разветвитель

((?:(?:\w+[+-])+)+\w+)(?=\s|$)|(?:^|\s)((?:\w+\s+)+\w+)(?=\s|$)

Опции: без учета регистра; ^ $ Не совпадают по линии ломает

$ 1 $ 2

Создано с помощью RegexBuddy

0 голосов
/ 01 сентября 2018

Грубо говоря, он делает то, что вам нужно.

sentence() = Split(10+20+30+40 50+60+70+80 123a 123 123b 345 123c 123 123d 123 90+100+110+120 123 123 231 123)

 For i = 0 To UBound(sentence)
  acu_str = sentence(i)
   If InStr(sentence(i), "+") = 0 And InStr(sentence(i), "-") = 0 Then
    Do While InStr(sentence(i + 1), "+") = 0 And InStr(sentence(i + 1), "-") = 0
    On Error GoTo ErrorHandling
     acu_str = acu_str + " " + sentence(i + 1)
    i = i + 1
    Loop
   ErrorHandling:
  End If
 Debug.Print acu_str & vbCr
 Next i
...