Как использовать регулярные выражения (регулярное выражение) в Microsoft Excel как внутри ячейки, так и в цикле

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

  • Функция в ячейке для возврата совпавшего шаблона или замененного значения в строке.
  • Sub для циклического перебора столбца данных и извлечения совпадений для соседних ячеек.
  • Какая настройка нужна?
  • Что такое специальные символы Excel для регулярных выражений?

Я понимаю, что Regex не идеален для многих ситуаций (использовать или не использовать регулярные выражения?), Так как Excel может использовать команды типа Left, Mid, Right, Instr для подобных манипуляций.

Ответ 1

Регулярные выражения используются для сопоставления шаблонов.

Для использования в Excel выполните следующие действия:

Шаг 1. Добавьте ссылку VBA на "Microsoft VBScript Regular Expressions 5.5".

  • Выберите вкладку "Разработчик" (у меня нет этой вкладки, что мне делать?)
  • Выберите значок "Visual Basic" в разделе "Код" ленты
  • В окне "Microsoft Visual Basic for Applications" выберите "Инструменты" в верхнем меню.
  • Выберите "Ссылки"
  • Установите флажок рядом с "Microsoft VBScript Regular Expressions 5.5", чтобы включить в свою книгу.
  • Нажмите "ОК"

Шаг 2: Определите свой шаблон

Основные определения:

- Диапазон.

  • Например, az соответствует строчным буквам от a до z
  • Например, 0-5 соответствует любому числу от 0 до 5

[] Совместите точно один из объектов внутри этих скобок.

  • Например, [a] соответствует букве a
  • Например, [abc] соответствует одной букве, которая может быть a, b или c
  • Например, [az] соответствует любой отдельной строчной букве алфавита.

() Группы разных матчей для целей возвращения. См. Примеры ниже.

{} Множитель для повторных копий шаблона, определенного перед ним.

  • Например, [a]{2} соответствует двум последовательным строчным буквам a: aa
  • Например, [a]{1,3} соответствует хотя бы одному и до трех строчных букв a, aa, aaa

+ Сопоставьте хотя бы один или несколько шаблонов, определенных перед ним.

  • Например, a+ будет соответствовать последовательно a, aa, aaa и т.д.

? Сопоставьте нуль или один из шаблонов, определенных перед ним.

  • Например, шаблон может присутствовать или не присутствовать, но его можно подобрать только один раз.
  • Например, [az]? соответствует пустой строке или любой отдельной строчной буквой.

* Сопоставьте ноль или больше шаблона, определенного перед ним. - Например, подстановочный шаблон для шаблона, который может быть или не быть. - Например, [az]* соответствует пустой строке или строке строчных букв.

. Соответствует любому символу, кроме новой строки \n

  • Например a. Соответствует двухсимвольной строке, начинающейся с a и заканчивающейся чем угодно, кроме \n

| Оператор OR

  • Например, a|b означает, что либо a либо b могут быть сопоставлены.
  • Например, red|white|orange соответствует точно одному из цветов.

^ NOT оператор

  • Например, символ [^0-9] не может содержать число
  • Например, символ [^aA] не может быть нижним регистром a или верхним регистром A

\ Вызывает специальный символ, который следует (переопределяет поведение выше)

  • Например \. , \\, \(, \? \$, \^

Шаблоны привязки:

^ Соответствие должно происходить в начале строки

  • Например, ^a первый символ должен быть строчной буквой a
  • Например ^[0-9] Первый символ должен быть числом.

$ Матч должен встречаться в конце строки

  • Например a$ символ a$ Last должен быть строчной буквой a

Таблица приоритетов:

Order  Name                Representation
1      Parentheses         ( )
2      Multipliers         ? + * {m,n} {m, n}?
3      Sequence & Anchors  abc ^ $
4      Alternation         |

Предопределенные сокращения символов:

abr    same as       meaning
\d     [0-9]         Any single digit
\D     [^0-9]        Any single character that not a digit
\w     [a-zA-Z0-9_]  Any word character
\W     [^a-zA-Z0-9_] Any non-word character
\s     [ \r\t\n\f]   Any space character
\S     [^ \r\t\n\f]  Any non-space character
\n     [\n]          New line

Пример 1. Выполнение макроса

В следующем примере макрос просматривает значение в ячейке A1 чтобы увидеть, являются ли первые 1 или 2 символа цифрами. Если это так, они удаляются, а остальная часть строки отображается. Если нет, появится окно с сообщением о том, что совпадения не найдено. Значения ячейки A1 12abc вернут abc, значение 1abc вернет abc, значение abc123 вернет "Not Matched", потому что цифры не были в начале строки.

Private Sub simpleRegex()
    Dim strPattern As String: strPattern = "^[0-9]{1,2}"
    Dim strReplace As String: strReplace = ""
    Dim regEx As New RegExp
    Dim strInput As String
    Dim Myrange As Range

    Set Myrange = ActiveSheet.Range("A1")

    If strPattern <> "" Then
        strInput = Myrange.Value

        With regEx
            .Global = True
            .MultiLine = True
            .IgnoreCase = False
            .Pattern = strPattern
        End With

        If regEx.Test(strInput) Then
            MsgBox (regEx.Replace(strInput, strReplace))
        Else
            MsgBox ("Not matched")
        End If
    End If
End Sub

Пример 2. Выполнение функции в ячейке

Этот пример такой же, как в примере 1, но настроен для работы в качестве встроенной функции. Чтобы использовать, измените код на это:

Function simpleCellRegex(Myrange As Range) As String
    Dim regEx As New RegExp
    Dim strPattern As String
    Dim strInput As String
    Dim strReplace As String
    Dim strOutput As String


    strPattern = "^[0-9]{1,3}"

    If strPattern <> "" Then
        strInput = Myrange.Value
        strReplace = ""

        With regEx
            .Global = True
            .MultiLine = True
            .IgnoreCase = False
            .Pattern = strPattern
        End With

        If regEx.test(strInput) Then
            simpleCellRegex = regEx.Replace(strInput, strReplace)
        Else
            simpleCellRegex = "Not matched"
        End If
    End If
End Function

Поместите свои строки ("12abc") в ячейку A1. Введите эту формулу =simpleCellRegex(A1) в ячейке B1 и результат будет "abc".

enter image description here


Пример 3: Диапазон прохождения циклы

Этот пример такой же, как в примере 1, но проходит через диапазон ячеек.

Private Sub simpleRegex()
    Dim strPattern As String: strPattern = "^[0-9]{1,2}"
    Dim strReplace As String: strReplace = ""
    Dim regEx As New RegExp
    Dim strInput As String
    Dim Myrange As Range

    Set Myrange = ActiveSheet.Range("A1:A5")

    For Each cell In Myrange
        If strPattern <> "" Then
            strInput = cell.Value

            With regEx
                .Global = True
                .MultiLine = True
                .IgnoreCase = False
                .Pattern = strPattern
            End With

            If regEx.Test(strInput) Then
                MsgBox (regEx.Replace(strInput, strReplace))
            Else
                MsgBox ("Not matched")
            End If
        End If
    Next
End Sub

Пример 4. Разделение разных шаблонов

Этот пример проходит через диапазон (A1, A2 и A3) и ищет строку, начинающуюся с трех цифр, за которой следует один альфа-символ, а затем 4 числовые цифры. Вывод разбивает совпадения шаблонов на соседние ячейки с помощью (). $1 представляет первый шаблон, сопоставляемый в первом наборе ().

Private Sub splitUpRegexPattern()
    Dim regEx As New RegExp
    Dim strPattern As String
    Dim strInput As String
    Dim Myrange As Range

    Set Myrange = ActiveSheet.Range("A1:A3")

    For Each C In Myrange
        strPattern = "(^[0-9]{3})([a-zA-Z])([0-9]{4})"

        If strPattern <> "" Then
            strInput = C.Value

            With regEx
                .Global = True
                .MultiLine = True
                .IgnoreCase = False
                .Pattern = strPattern
            End With

            If regEx.test(strInput) Then
                C.Offset(0, 1) = regEx.Replace(strInput, "$1")
                C.Offset(0, 2) = regEx.Replace(strInput, "$2")
                C.Offset(0, 3) = regEx.Replace(strInput, "$3")
            Else
                C.Offset(0, 1) = "(Not matched)"
            End If
        End If
    Next
End Sub

Результаты:

enter image description here


Дополнительные примеры шаблонов

String   Regex Pattern                  Explanation
a1aaa    [a-zA-Z][0-9][a-zA-Z]{3}       Single alpha, single digit, three alpha characters
a1aaa    [a-zA-Z]?[0-9][a-zA-Z]{3}      May or may not have preceeding alpha character
a1aaa    [a-zA-Z][0-9][a-zA-Z]{0,3}     Single alpha, single digit, 0 to 3 alpha characters
a1aaa    [a-zA-Z][0-9][a-zA-Z]*         Single alpha, single digit, followed by any number of alpha characters

</i8>    \<\/[a-zA-Z][0-9]\>            Exact non-word character except any single alpha followed by any single digit

Ответ 2

Чтобы использовать регулярные выражения непосредственно в формулах Excel, может помочь следующая UDF (пользовательская функция). Он более или менее напрямую предоставляет функциональность регулярных выражений как функцию excel.

Как это работает

Требуется 2-3 параметра.

  • Текст для использования регулярного выражения.
  • Регулярное выражение.
  • Строка формата, определяющая, как должен выглядеть результат. Он может содержать $0, $1, $2 и т.д. $0 - полное совпадение, $1 и up соответствуют соответствующим группам совпадений в регулярном выражении. По умолчанию $0.

Некоторые примеры

Извлечение адреса электронной почты:

=regex("Peter Gordon: [email protected], 47", "\[email protected]\w+\.\w+")
=regex("Peter Gordon: [email protected], 47", "\[email protected]\w+\.\w+", "$0")

Результаты в: [email protected]

Извлечение нескольких подстрок:

=regex("Peter Gordon: [email protected], 47", "^(.+): (.+), (\d+)$", "E-Mail: $2, Name: $1")

Результаты в: E-Mail: [email protected], Name: Peter Gordon

Разделить объединенную строку в одной ячейке на ее компоненты в нескольких ячейках:

=regex("Peter Gordon: [email protected], 47", "^(.+): (.+), (\d+)$", "$" & 1)
=regex("Peter Gordon: [email protected], 47", "^(.+): (.+), (\d+)$", "$" & 2)

Результаты в: Peter Gordon [email protected]...

Как использовать

Чтобы использовать этот UDF, сделайте следующее (примерно на основе эта страница Microsoft. У них есть дополнительная дополнительная информация!):

  • В Excel в файле с поддержкой макроса (.xlsm) нажмите ALT+F11, чтобы открыть редактор Microsoft Visual Basic для приложений.
  • Добавьте ссылку VBA в библиотеку регулярных выражений (бесстыдно скопированную из ответ Portland Runners ++):
    • Нажмите Инструменты → Ссылки (пожалуйста, извините немецкий скриншот) Tools -> References
    • Найдите в списке Microsoft VBScript Regular Expressions 5.5 и установите галочку рядом с ним.
    • Нажмите "ОК".
  • Нажмите "Вставить модуль". Если вы укажете вашему модулю другое имя, убедитесь, что модуль не имеет того же имени, что и UDF (например, имя модуля Regex, а функция Regex вызывает ошибки #NAME!).

    Second icon in the icon row -> Module

  • В большом текстовом окне в середине вставьте следующее:

    Function regex(strInput As String, matchPattern As String, Optional ByVal outputPattern As String = "$0") As Variant
        Dim inputRegexObj As New VBScript_RegExp_55.RegExp, outputRegexObj As New VBScript_RegExp_55.RegExp, outReplaceRegexObj As New VBScript_RegExp_55.RegExp
        Dim inputMatches As Object, replaceMatches As Object, replaceMatch As Object
        Dim replaceNumber As Integer
    
        With inputRegexObj
            .Global = True
            .MultiLine = True
            .IgnoreCase = False
            .Pattern = matchPattern
        End With
        With outputRegexObj
            .Global = True
            .MultiLine = True
            .IgnoreCase = False
            .Pattern = "\$(\d+)"
        End With
        With outReplaceRegexObj
            .Global = True
            .MultiLine = True
            .IgnoreCase = False
        End With
    
        Set inputMatches = inputRegexObj.Execute(strInput)
        If inputMatches.Count = 0 Then
            regex = False
        Else
            Set replaceMatches = outputRegexObj.Execute(outputPattern)
            For Each replaceMatch In replaceMatches
                replaceNumber = replaceMatch.SubMatches(0)
                outReplaceRegexObj.Pattern = "\$" & replaceNumber
    
                If replaceNumber = 0 Then
                    outputPattern = outReplaceRegexObj.Replace(outputPattern, inputMatches(0).Value)
                Else
                    If replaceNumber > inputMatches(0).SubMatches.Count Then
                        'regex = "A to high $ tag found. Largest allowed is $" & inputMatches(0).SubMatches.Count & "."
                        regex = CVErr(xlErrValue)
                        Exit Function
                    Else
                        outputPattern = outReplaceRegexObj.Replace(outputPattern, inputMatches(0).SubMatches(replaceNumber - 1))
                    End If
                End If
            Next
            regex = outputPattern
        End If
    End Function
    
  • Сохраните и закройте окно Microsoft Visual Basic для редактора приложений.

Ответ 3

Развернуть patszim ответ для тех, кто спешит.

  • Откройте книгу Excel.
  • Alt + F11, чтобы открыть окно VBA/Макросы.
  • Добавьте ссылку на регулярное выражение в Инструменты, затем Ссылки
    ! [Excel VBA Form add references
  • и выбрав Microsoft VBScript Regular Expression 5.5
    ! [Excel VBA add regex reference
  • Вставьте новый модуль (код должен находиться в модуле, иначе он не будет работать).
    ! [Модуль ввода кода Excel VBA
  • Во вновь вставленном модуле,
    ! [Excel VBA вставить код в модуль
  • добавьте следующий код:

    Function RegxFunc(strInput As String, regexPattern As String) As String
        Dim regEx As New RegExp
        With regEx
            .Global = True
            .MultiLine = True
            .IgnoreCase = False
            .pattern = regexPattern
        End With
    
        If regEx.Test(strInput) Then
            Set matches = regEx.Execute(strInput)
            RegxFunc = matches(0).Value
        Else
            RegxFunc = "not matched"
        End If
    End Function
    
  • Шаблон регулярного выражения помещается в одну из ячеек, и на нем используется абсолютная ссылка. ! [Функция регулярного выражения в ячеек в ячейке Функция будет привязана к книге, которую она создала.
    Если есть необходимость, чтобы он использовался в разных книгах, сохраните функцию в Personal.XLSB

Ответ 4

Вот моя попытка:

Function RegParse(ByVal pattern As String, ByVal html As String)
    Dim regex   As RegExp
    Set regex = New RegExp

    With regex
        .IgnoreCase = True  'ignoring cases while regex engine performs the search.
        .pattern = pattern  'declaring regex pattern.
        .Global = False     'restricting regex to find only first match.

        If .Test(html) Then         'Testing if the pattern matches or not
            mStr = .Execute(html)(0)        '.Execute(html)(0) will provide the String which matches with Regex
            RegParse = .Replace(mStr, "$1") '.Replace function will replace the String with whatever is in the first set of braces - $1.
        Else
            RegParse = "#N/A"
        End If

    End With
End Function

Ответ 5

Мне нужно было использовать это как функцию ячейки (например, SUM или VLOOKUP) и обнаружил, что это легко:

  1. Убедитесь, что вы находитесь в Macro Enabled Excel File (сохранить как xlsm).
  2. Открытые инструменты разработчика Alt + F11
  3. Добавьте регулярные выражения Microsoft VBScript 5.5, как в других ответах
  4. Создайте следующую функцию в книге или в ее собственном модуле:

    Function REGPLACE(myRange As Range, matchPattern As String, outputPattern As String) As Variant
        Dim regex As New VBScript_RegExp_55.RegExp
        Dim strInput As String
    
        strInput = myRange.Value
    
        With regex
            .Global = True
            .MultiLine = True
            .IgnoreCase = False
            .Pattern = matchPattern
        End With
    
        REGPLACE = regex.Replace(strInput, outputPattern)
    
    End Function
    
  5. Затем вы можете использовать в ячейке с =REGPLACE(B1, "(\w) (\d+)", "$1$2") (например: "A 243" - "A243")

Ответ 6

Вот regex_subst(). Примеры:

=regex_subst("watermellon", "[aeiou]", "")
---> wtrmlln
=regex_subst("watermellon", "[^aeiou]", "")
---> aeeo

Вот упрощенный код (проще для меня, во всяком случае). Я не мог понять, как создать подходящую модель вывода, используя приведенное выше, чтобы работать как мои примеры:

Function regex_subst( _
     strInput As String _
   , matchPattern As String _
   , Optional ByVal replacePattern As String = "" _
) As Variant
    Dim inputRegexObj As New VBScript_RegExp_55.RegExp

    With inputRegexObj
        .Global = True
        .MultiLine = True
        .IgnoreCase = False
        .Pattern = matchPattern
    End With

    regex_subst = inputRegexObj.Replace(strInput, replacePattern)
End Function

Ответ 7

Я не хочу включать справочную библиотеку, так как мне нужно, чтобы мои сценарии были переносимыми. Строка Dim foo As New VBScript_RegExp_55.RegExp вызвала ошибки User Defined Type Not Defined, но я нашел решение, которое сработало для меня.

То, что вы хотите сделать, это поместить пример строки в ячейку A1, а затем протестировать ваш strPattern. Как только это сработает, отрегулируйте rng по желанию.

Public Sub RegExSearch()
'https://stackoverflow.com/info/22542834/how-to-use-regular-expressions-regex-in-microsoft-excel-both-in-cell-and-loops
'https://wellsr.com/vba/2018/excel/vba-regex-regular-expressions-guide/
'https://www.vitoshacademy.com/vba-regex-in-excel/
    Dim regexp As Object
    'Dim regex As New VBScript_RegExp_55.regexp 'Caused "User Defined Type Not Defined" Error
    Dim rng As Range, rcell As Range
    Dim strInput As String, strPattern As String

    Set regexp = CreateObject("vbscript.regexp")
    Set rng = ActiveSheet.Range("A1:A1")

    For Each rcell In rng.Cells

        strPattern = "([a-z]{2})([0-9]{8})"
        'Search for 2 Letters then 8 Digits Eg: XY12345678 = Matched

        With regexp
            .Global = False
            .MultiLine = False
            .ignoreCase = True
            .Pattern = strPattern
        End With

        If strPattern <> "" Then
            strInput = rcell.Value

            If regexp.test(strInput) Then
                MsgBox rcell & " Matched in Cell " & rcell.Address
            Else
                MsgBox "No Matches!"
            End If
        End If
    Next
End Sub