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

439

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

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

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

  • 7
    Я настоятельно рекомендую эту статью VB / VBA Regexp Патрика Мэтьюса
  • 0
    Попробуйте это бесплатное дополнение: seotoolsforexcel.com/regexpfind
Показать ещё 2 комментария
Теги:
excel-vba
excel

6 ответов

752
Лучший ответ

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

Для использования в 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".

Изображение 3701


Пример 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

Результаты:

Изображение 3702


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

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
  • 14
    Вы не должны забывать Set regEx = Nothing . Вы получите исключения «Недостаточно памяти», когда этот саб выполняется достаточно часто.
  • 1
    Я адаптировал пример 4 с SubMatches для обработки более сложных регулярных выражений, в основном я не использую замену при разбиении, если кому-то интересно: stackoverflow.com/questions/30218413/…
Показать ещё 7 комментариев
162

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

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

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

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

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

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

=regex("Peter Gordon: [email protected], 47", "\w+@\w+\.\w+")
=regex("Peter Gordon: [email protected], 47", "\w+@\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 ++):
    • Нажмите Инструменты → Ссылки (пожалуйста, извините немецкий скриншот) Изображение 3703
    • Найдите в списке Microsoft VBScript Regular Expressions 5.5 и установите галочку рядом с ним.
    • Нажмите "ОК".
  • Нажмите "Вставить модуль". Если вы укажете вашему модулю другое имя, убедитесь, что модуль не имеет того же имени, что и UDF (например, имя модуля Regex, а функция Regex вызывает ошибки #NAME!).

    Изображение 3704

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

    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 для редактора приложений.

  • 5
    Ответ на этот вопрос в сочетании с шагами здесь , чтобы создать Add-In, было очень полезно. Спасибо. Убедитесь, что вы не называете свой модуль и работаете с тем же именем!
  • 2
    Просто повторяю комментарий выше от Криса Ханта. Также не называйте свой модуль "Regex". Я думал, что на какое-то время схожу с ума, так как функция не работает из-за ошибки #NAME
Показать ещё 3 комментария
33

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

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

    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
    
  • Шаблон регулярного выражения помещается в одну из ячеек, и на нем используется абсолютная ссылка. Изображение 3709 Функция будет привязана к книге, которую она создала.
    Если есть необходимость, чтобы он использовался в разных книгах, сохраните функцию в Personal.XLSB

16

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

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
1

Вот 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
1

Мне нужно было использовать это как функцию ячейки (например, 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")

  • 0
    Это наименование outputPattern отбросило меня. Это восстановительная стоимость.
  • 1
    Да. Я полагаю, я оставил его с именем pattern, чтобы было ясно, что это не просто подстановка строк, и вы можете использовать группы сопоставления регулярных выражений, такие как $ 1 $ 2 и т. Д.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню