Регулярное выражение VBA: извлечение нескольких строк между строками в ячейке Excel с помощью пользовательской функции

В столбце Excel у меня есть такие данные, как:

Audi (ADI), Mercedes (modelx) (MEX), Ferrari super fast, high PS (FEH)

Существуют сотни моделей, которые описываются названием и аббревиатурой из трех заглавных букв в скобках.

Мне нужно извлечь только имена и аббревиатуры только для разделения ячеек. Мне удалось сделать это для аббревиатур с помощью следующего модуля:

Function extrABR(cellRef) As String
    Dim RE As Object, MC As Object, M As Object
    Dim sTemp As Variant
    Const sPat As String = "([A-Z][A-Z][A-Z][A-Z]?)"  ' this is my regex to match my string
    
    
Set RE = CreateObject("vbscript.regexp")
With RE
    .Global = True
    .MultiLine = True
    .Pattern = sPat
    If .Test(cellRef) Then
        Set MC = .Execute(cellRef)
        For Each M In MC
            sTemp = sTemp & ", " & M.SubMatches(0)
        Next M
    End If
End With

extrABR = Mid(sTemp, 3)

End Function 

Однако мне не удается сделать это для имен. Я думал просто заменить регулярное выражение на следующее регулярное выражение: (^(.*?)(?= \([A-Z][A-Z][A-Z])|(?<=, )(.*)(?= \([A-Z][A-Z][A-Z])), но VBA, похоже, не позволяет смотреть назад.

Есть идеи?


person MsGISRocker    schedule 12.07.2021    source источник
comment
Вы получите набор сокращений с "\([^)]+\)" ... и при втором совпадении замените все с , вы получите строку без сокращений, которую затем можно разделить на имена.   -  person Naresh    schedule 12.07.2021
comment
Вы имеете в виду, что вам нужно получить массив Audi, Mercedes (modelx) и Ferrari super fast, high PS?   -  person Wiktor Stribiżew    schedule 12.07.2021


Ответы (2)


Правильно, просмотр назад не поддерживается, но он необходим только тогда, когда ваши ожидаемые совпадения перекрываются. Здесь это не так, все ваши совпадения не перекрываются. Итак, вы снова можете положиться на захват:

(?:^|,)\s*(.*?)(?=\s*\([A-Z]{3,}\))

См. демонстрацию регулярного выражения. Доступ к значениям группы 1 осуществляется через .Submatches(0).

Подробности:

  • (?:^|,) - либо начало строки, либо запятая
  • \s* - ноль или более пробельных символов
  • (.*?) - Группа захвата 1: любой ноль или более символов, кроме символов разрыва строки, как можно меньше
  • (?=\s*\([A-Z]{3,}\)) - a positive lookahead that matches a location that is immediately followed with
    • \s* - zero or more whitespace chars
    • \( - символ (
    • [A-Z]{3,} - три или более заглавных буквы
    • \) - ) символ.

Скриншот демо:

введите здесь описание изображения

person Wiktor Stribiżew    schedule 12.07.2021
comment
Здорово узнать об этом .. Может быть, OP ожидает максимум 4 заглавных буквы между скобками. Итак, можем ли мы заменить ([A-Z]{3,} на ([A-Z]{4,}, и это будет соответствовать 3 или 4 заглавным буквам? - person Naresh; 12.07.2021
comment
@Naresh Чтобы соответствовать трем или четырем, следует использовать [A-Z]{3,4}. - person Wiktor Stribiżew; 12.07.2021
comment
Понял. Спасибо. Я просто просматривал эти документы Страница .microsoft.com - person Naresh; 12.07.2021

RE.REPLACE -- попробуйте эту функцию. Все, что находится между круглыми скобками, будет заменено только строкой имен моделей, которую затем можно разделить на запятую и получить массив строк, если это необходимо.

Function ModelNames(cellRef) As String
    Dim RE As Object, MC As Object, M As Object
    Dim sTemp As Variant, sPat As String
    sPat = "\([^)]+\)"
'Or you can use your formula pattern "([A-Z][A-Z][A-Z][A-Z]?)" to get (modelx)  in the final output.

Set RE = CreateObject("vbscript.regexp")
With RE
    .Global = True
    .MultiLine = True
    .Pattern = sPat
End With

ModelNames = RE.Replace(cellRef, "")

End Function
person Naresh    schedule 12.07.2021