Регулярные выражения в VBA Excel. Объекты RegExp, Match, Matches Collection и их свойства. Символы и метасимволы. Создание объекта RegExp с ранней, поздней привязкой и его методы.
Регулярные выражения (по Википедии) – это формальный язык поиска и осуществления манипуляций с подстроками в тексте. Они используются для обработки текстов с помощью шаблонов, состоящих из символов и метасимволов, и представлены объектом RegExp.
В VBA Excel для работы с регулярными выражениями используется библиотека «Microsoft VBScript Regular Expression».
Создание объекта RegExp
Ранняя привязка
Обычно рекомендуется использовать объекты с ранней привязкой, так как у них выше быстродействие, а также при написании и редактировании кода доступны подсказки в виде листа свойств-методов, появляющегося автоматически или вызываемого, при необходимости, сочетанием клавиш Ctrl+Пробел.
Раннее связывание заключается в присвоении нового экземпляра объекта RegExp переменной, уже объявленной, как переменная определенного типа (в нашем случае, как RegExp).
Для осуществления ранней привязки необходимо подключить к проекту VBA ссылку на библиотеку «Microsoft VBScript Regular Expression», для чего в редакторе VBA выбираем Tools — References…
В открывшемся окне «References» находим строку «Microsoft VBScript Regular Expression 5.5» (если у вас ее нет, то строку «Microsoft VBScript Regular Expression 1.0»), отмечаем ее галочкой и нажимаем «ОК».
Готово — ссылка добавлена.
Создание объекта RegExp с ранней привязкой:
‘Вариант 1 Dim myRegExp As RegExp Set myRegExp = New RegExp ‘————————- ‘Вариант 2 Dim myRegExp As New RegExp |
Поздняя привязка
Позднее связывание заключается в присвоении нового экземпляра объекта RegExp переменной, объявленной как Object, с помощью функции CreateObject.
Создание объекта RegExp с поздней привязкой:
Dim myRegExp As Object Set myRegExp = CreateObject(«VBScript.RegExp») |
Свойства и методы объекта RegExp
Свойства объекта RegExp
Свойство | Описание | Значение по умолчанию |
---|---|---|
Global | Определяет продолжительность поиска: False — до первого совпадения True — по всему тексту |
False |
IgnoreCase | Определяет чувствительность к регистру символов: False — учитывать регистр True — не учитывать регистр |
False |
Multiline | Определяет структуру объекта: False — однострочный True — многострочный |
False |
Pattern | Строка, используемая как шаблон | Пустая строка |
Свойства объекта RegExp доступны для чтения и записи.
Методы объекта RegExp
Метод | Синтаксис | Описание |
---|---|---|
Execute | Execute(myStr) myStr — строка для поиска |
Возвращает коллекцию найденных по шаблону подстрок в виде агрегатного объекта |
Replace | Replace(myStr,myRep) myStr — строка для поиска myRep — строка для замены |
Возвращает строку, в которой найденные по шаблону вхождения в исходной строке заменены на указанную подстроку. |
Test | Test(myText) myText — строка для проверки |
Возвращает булево значение как результат проверки соответствия строки шаблону |
Свойства объектов Match и Matches Collection
Метод Execute объекта RegExp возвращает агрегатный объект Matches Collection, который содержит коллекцию объектов Match, представляющих все совпадения, найденные механизмом регулярных выражений, в том порядке, в котором они присутствуют в исходной строке. Если совпадений нет, метод возвращает объект Matches Collection без членов.
Свойства объекта Matches Collection
Свойство | Описание |
---|---|
Count | Количество объектов Match, содержащихся в объекте Matches Collection |
Item | Индекс члена коллекции от нуля до значения свойства Count минус 1 |
Свойства объекта Matches Collection доступны только для чтения.
Свойства объекта Match
Свойство | Описание |
---|---|
FirstIndex | Позиция в исходной строке, где произошло совпадение, причем первая позиция в строке равна нулю |
Length | Длина совпавшей подстроки |
Value | Найденная подстрока (является свойством по умолчанию) |
Свойства объекта Match доступны только для чтения.
Символы и метасимволы
Все знаки, используемые для составления шаблонов, обычно делят на символы и метасимволы. Символы — это знаки, которые в шаблонах обозначают сами себя, а метасимволы (спецсимволы) — знаки, имеющие другое значение. Метасимволы могут использоваться как отдельно, так и в сочетании с другими символами и спецсимволами.
Таблица основных метасимволов и их сочетаний с другими символами
Метасимвол (сочетание символов) |
Значение |
---|---|
После этого знака метасимвол обозначает сам себя, а некоторые символы приобретают другое значение | |
^ | Начало строки |
$ | Конец строки |
? | Ни одного или один любой символ |
* | Ни одного или несколько любых символов |
+ | Один или несколько любых символов |
. | Любой символ, кроме знака «новая строка» |
— | Определяет интервал символов |
| | Знак «или» |
{n} | Точное количество символов, стоящих перед {n} |
{n,m} | Количество от n до m символов, стоящих перед {n,m} |
[abc] | Любой из указанных символов |
[^abc] | Любой из неуказанных символов |
[a-z] | Любой символ из диапазона |
[^a-z] | Любой символ, не входящий в диапазон |
b | Конец слова |
B | Не конец слова |
d | Цифра |
D | Не цифра |
w | Любая буква, цифра или знак подчеркивания |
W | Не буква, не цифра и не знак подчеркивания |
s | Пробел |
S | Не пробел |
В таблицу не включены редко используемые сочетания, ознакомиться с которыми можно в справочной системе разработчика. А примеры использования метасимволов в шаблонах очень хорошо представлены на этом ресурсе в разделе 4. Метасимволы.
Пример использования RegExp
Пример использования регулярных выражений в VBA Excel для извлечения email-адресов из текстового файла.
Для извлечения текстовой информации из файла в переменную используется функция GetText, которую вы можете скопировать из статьи Парсинг сайтов, html-страниц и файлов.
В файл «Новый документ.txt» вставлен произвольный текст с четырьмя примерами email-адресов, которые необходимо извлечь.
Код VBA Excel для извлечения email-адресов из текстового файла с помощью регулярных выражений:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
Sub Primer() Dim htmlText As String, myRegExp As Object, myObj As Object, myStr1 As Object, myStr2 As String ‘Присваиваем переменной htmlText текстовую информацию из файла «Новый документ.txt» htmlText = GetText(«C:UsersEvgeniyDownloadsНовый документ.txt») ‘Присваиваем переменной myRegExp ссылку на новый экземпляр RegExp Set myRegExp = CreateObject(«VBScript.RegExp») With myRegExp ‘Задаем поиск по всему тексту .Global = True ‘Задаем шаблон поиска .Pattern = «([w.-]+)@([w.-]+).([A-Za-z]{2,6})» ‘Присваиваем переменной myObj коллекцию найденных по шаблону email-адресов Set myObj = .Execute(htmlText) End With For Each myStr1 In myObj ‘Извлекаем email-адреса из коллекции myObj по очереди в объектную переменную myStr1 ‘и записываем их построчно в текстовую переменную myStr2 myStr2 = myStr2 & myStr1 & vbNewLine Next ‘Смотрим, что получилось MsgBox myStr2 End Sub |
У меня результат работы кода выглядел так:
Regular expressions are used for Pattern Matching.
To use in Excel follow these steps:
Step 1: Add VBA reference to «Microsoft VBScript Regular Expressions 5.5»
- Select «Developer» tab (I don’t have this tab what do I do?)
- Select «Visual Basic» icon from ‘Code’ ribbon section
- In «Microsoft Visual Basic for Applications» window select «Tools» from the top menu.
- Select «References»
- Check the box next to «Microsoft VBScript Regular Expressions 5.5» to include in your workbook.
- Click «OK»
Step 2: Define your pattern
Basic definitions:
-
Range.
- E.g.
a-z
matches an lower case letters from a to z - E.g.
0-5
matches any number from 0 to 5
[]
Match exactly one of the objects inside these brackets.
- E.g.
[a]
matches the letter a - E.g.
[abc]
matches a single letter which can be a, b or c - E.g.
[a-z]
matches any single lower case letter of the alphabet.
()
Groups different matches for return purposes. See examples below.
{}
Multiplier for repeated copies of pattern defined before it.
- E.g.
[a]{2}
matches two consecutive lower case letter a:aa
- E.g.
[a]{1,3}
matches at least one and up to three lower case lettera
,aa
,aaa
+
Match at least one, or more, of the pattern defined before it.
- E.g.
a+
will match consecutive a’sa
,aa
,aaa
, and so on
?
Match zero or one of the pattern defined before it.
- E.g. Pattern may or may not be present but can only be matched one time.
- E.g.
[a-z]?
matches empty string or any single lower case letter.
*
Match zero or more of the pattern defined before it.
- E.g. Wildcard for pattern that may or may not be present.
- E.g.
[a-z]*
matches empty string or string of lower case letters.
.
Matches any character except newline n
- E.g.
a.
Matches a two character string starting with a and ending with anything exceptn
|
OR operator
- E.g.
a|b
means eithera
orb
can be matched. - E.g.
red|white|orange
matches exactly one of the colors.
^
NOT operator
- E.g.
[^0-9]
character can not contain a number - E.g.
[^aA]
character can not be lower casea
or upper caseA
Escapes special character that follows (overrides above behavior)
- E.g.
.
,\
,(
,?
,$
,^
Anchoring Patterns:
^
Match must occur at start of string
- E.g.
^a
First character must be lower case lettera
- E.g.
^[0-9]
First character must be a number.
$
Match must occur at end of string
- E.g.
a$
Last character must be lower case lettera
Precedence table:
Order Name Representation
1 Parentheses ( )
2 Multipliers ? + * {m,n} {m, n}?
3 Sequence & Anchors abc ^ $
4 Alternation |
Predefined Character Abbreviations:
abr same as meaning
d [0-9] Any single digit
D [^0-9] Any single character that's not a digit
w [a-zA-Z0-9_] Any word character
W [^a-zA-Z0-9_] Any non-word character
s [ rtnf] Any space character
S [^ rtnf] Any non-space character
n [n] New line
Example 1: Run as macro
The following example macro looks at the value in cell A1
to see if the first 1 or 2 characters are digits. If so, they are removed and the rest of the string is displayed. If not, then a box appears telling you that no match is found. Cell A1
values of 12abc
will return abc
, value of 1abc
will return abc
, value of abc123
will return «Not Matched» because the digits were not at the start of the string.
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
Example 2: Run as an in-cell function
This example is the same as example 1 but is setup to run as an in-cell function. To use, change the code to this:
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
Place your strings («12abc») in cell A1
. Enter this formula =simpleCellRegex(A1)
in cell B1
and the result will be «abc».
Example 3: Loop Through Range
This example is the same as example 1 but loops through a range of cells.
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
Example 4: Splitting apart different patterns
This example loops through a range (A1
, A2
& A3
) and looks for a string starting with three digits followed by a single alpha character and then 4 numeric digits. The output splits apart the pattern matches into adjacent cells by using the ()
. $1
represents the first pattern matched within the first set of ()
.
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
Results:
Additional Pattern Examples
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 preceding 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
Одной из самых трудоемких и неприятных задач при работе с текстом в Excel является парсинг — разбор буквенно-цифровой «каши» на составляющие и извлечение из нее нужных нам фрагментов. Например:
- извлечение почтового индекса из адреса (хорошо, если индекс всегда в начале, а если нет?)
- нахождение номера и даты счета из описания платежа в банковской выписке
- извлечение ИНН из разношерстных описаний компаний в списке контрагентов
- поиск номера автомобиля или артикула товара в описании и т.д.
Обычно во подобных случаях, после получасового муторного ковыряния в тексте вручную, в голову начинают приходить мысли как-то автоматизировать этот процесс (особенно если данных много). Решений тут несколько и с разной степенью сложности-эффективности:
- Использовать встроенные текстовые функции Excel для поиска-нарезки-склейки текста: ЛЕВСИМВ (LEFT), ПРАВСИМВ (RIGHT), ПСТР (MID), СЦЕПИТЬ (CONCATENATE) и ее аналоги, ОБЪЕДИНИТЬ (JOINTEXT), СОВПАД (EXACT) и т.д. Этот способ хорош, если в тексте есть четкая логика (например, индекс всегда в начале адреса). В противном случае формулы существенно усложняются и, порой, дело доходит даже до формул массива, что сильно тормозит на больших таблицах.
- Использование оператора проверки текстового подобия Like из Visual Basic, обернутого в пользовательскую макро-функцию. Это позволяет реализовать более гибкий поиск с использованием символов подстановки (*,#,? и т.д.) К сожалению, этот инструмент не умеет извлекать нужную подстроку из текста — только проверять, содержится ли она в нем.
Кроме вышеперечисленного, есть еще один подход, очень известный в узких кругах профессиональных программистов, веб-разработчиков и прочих технарей — это регулярные выражения (Regular Expressions = RegExp = «регэкспы» = «регулярки»). Упрощенно говоря, RegExp — это язык, где с помощью специальных символов и правил производится поиск нужных подстрок в тексте, их извлечение или замена на другой текст. Регулярные выражения — это очень мощный и красивый инструмент, на порядок превосходящий по возможностям все остальные способы работы с текстом. Многие языки программирования (C#, PHP, Perl, JavaScript…) и текстовые редакторы (Word, Notepad++…) поддерживают регулярные выражения.
Microsoft Excel, к сожалению, не имеет поддержки RegExp по-умолчанию «из коробки», но это легко исправить с помощью VBA. Откройте редактор Visual Basic с вкладки Разработчик (Developer) или сочетанием клавиш Alt+F11. Затем вставьте новый модуль через меню Insert — Module и скопируйте туда текст вот такой макрофункции:
Public Function RegExpExtract(Text As String, Pattern As String, Optional Item As Integer = 1) As String On Error GoTo ErrHandl Set regex = CreateObject("VBScript.RegExp") regex.Pattern = Pattern regex.Global = True If regex.Test(Text) Then Set matches = regex.Execute(Text) RegExpExtract = matches.Item(Item - 1) Exit Function End If ErrHandl: RegExpExtract = CVErr(xlErrValue) End Function
Теперь можно закрыть редактор Visual Basic и, вернувшись в Excel, опробовать нашу новую функцию. Синтаксис у нее следующий:
=RegExpExtract( Txt ; Pattern ; Item )
где
- Txt — ячейка с текстом, который мы проверяем и из которого хотим извлечь нужную нам подстроку
- Pattern — маска (шаблон) для поиска подстроки
- Item — порядковый номер подстроки, которую надо извлечь, если их несколько (если не указан, то выводится первое вхождение)
Самое интересное тут, конечно, это Pattern — строка-шаблон из спецсимволов «на языке» RegExp, которая и задает, что именно и где мы хотим найти. Вот самые основные из них — для начала:
Паттерн | Описание |
. | Самое простое — это точка. Она обозначает любой символ в шаблоне на указанной позиции. |
s | Любой символ, выглядящий как пробел (пробел, табуляция или перенос строки). |
S | Анти-вариант предыдущего шаблона, т.е. любой НЕпробельный символ. |
d | Любая цифра |
D | Анти-вариант предыдущего, т.е. любая НЕ цифра |
w | Любой символ латиницы (A-Z), цифра или знак подчеркивания |
W | Анти-вариант предыдущего, т.е. не латиница, не цифра и не подчеркивание. |
[символы] |
В квадратных скобках можно указать один или несколько символов, разрешенных на указанной позиции в тексте. Например ст[уо]л будет соответствовать любому из слов: стол или стул. Также можно не перечислять символы, а задать их диапазоном через дефис, т.е. вместо [ABDCDEF] написать [A-F]. или вместо [4567] ввести [4-7]. Например, для обозначения всех символов кириллицы можно использовать шаблон [а-яА-ЯёЁ]. |
[^символы] | Если после открывающей квадратной скобки добавить символ «крышки» ^, то набор приобретет обратный смысл — на указанной позиции в тексте будут разрешены все символы, кроме перечисленных. Так, шаблон [^ЖМ]уть найдет Путь или Суть или Забудь, но не Жуть или Муть, например. |
| | Логический оператор ИЛИ (OR) для проверки по любому из указанных критериев. Например (счет|счёт|invoice) будет искать в тексте любое из указанных слов. Обычно набор вариантов заключается в скобки. |
^ | Начало строки |
$ | Конец строки |
b | Край слова |
Если мы ищем определенное количество символов, например, шестизначный почтовый индекс или все трехбуквенные коды товаров, то на помощь нам приходят квантификаторы или кванторы — специальные выражения, задающие количество искомых знаков. Квантификаторы применяются к тому символу, что стоит перед ним:
Квантор | Описание |
? | Ноль или одно вхождение. Например .? будет означать один любой символ или его отсутствие. |
+ | Одно или более вхождений. Например d+ означает любое количество цифр (т.е. любое число от 0 до бесконечности). |
* | Ноль или более вхождений, т.е. любое количество. Так s* означает любое количество пробелов или их отсутствие. |
{число} или {число1,число2} |
Если нужно задать строго определенное количество вхождений, то оно задается в фигурных скобках. Например d{6} означает строго шесть цифр, а шаблон s{2,5} — от двух до пяти пробелов |
Теперь давайте перейдем к самому интересному — разбору применения созданной функции и того, что узнали о паттернах на практических примерах из жизни.
Извлекаем числа из текста
Для начала разберем простой случай — нужно извлечь из буквенно-цифровой каши первое число, например мощность источников бесперебойного питания из прайс-листа:
Логика работы регулярного выражения тут простая: d — означает любую цифру, а квантор + говорит о том, что их количество должно быть одна или больше. Двойной минус перед функцией нужен, чтобы «на лету» преобразовать извлеченные символы в полноценное число из числа-как-текст.
Почтовый индекс
На первый взгляд, тут все просто — ищем ровно шесть цифр подряд. Используем спецсимвол d для цифры и квантор {6} для количества знаков:
Однако, возможна ситуация, когда левее индекса в строке стоит еще один большой набор цифр подряд (номер телефона, ИНН, банковский счет и т.д.) Тогда наша регулярка выдернет из нее первых 6 цифр, т.е. сработает некорректно:
Чтобы этого не происходило, необходимо добавить в наше регулярное выражение по краям модификатор b означающий конец слова. Это даст понять Excel, что нужный нам фрагмент (индекс) должен быть отдельным словом, а не частью другого фрагмента (номера телефона):
Телефон
Проблема с нахождением телефонного номера среди текста состоит в том, что существует очень много вариантов записи номеров — с дефисами и без, через пробелы, с кодом региона в скобках или без и т.д. Поэтому, на мой взгляд, проще сначала вычистить из исходного текста все эти символы с помощью нескольких вложенных друг в друга функций ПОДСТАВИТЬ (SUBSTITUTE), чтобы он склеился в единое целое, а потом уже примитивной регуляркой d{11} вытаскивать 11 цифр подряд:
ИНН
Тут чуть сложнее, т.к. ИНН (в России) бывает 10-значный (у юрлиц) или 12-значный (у физлиц). Если не придираться особо, то вполне можно удовлетвориться регуляркой d{10,12}, но она, строго говоря, будет вытаскивать все числа от 10 до 12 знаков, т.е. и ошибочно введенные 11-значные. Правильнее будет использовать два шаблона, связанных логическим ИЛИ оператором | (вертикальная черта):
Обратите внимание, что в запросе мы сначала ищем 12-разрядные, и только потом 10-разрядные числа. Если же записать нашу регулярку наоборот, то она будет вытаскивать для всех, даже длинных 12-разрядных ИНН, только первые 10 символов. То есть после срабатывания первого условия дальнейшая проверка уже не производится:
Это принципиальное отличие оператора | от стандартной экселевской логической функции ИЛИ (OR), где от перестановки аргументов результат не меняется.
Артикулы товаров
Во многих компаниях товарам и услугам присваиваются уникальные идентификаторы — артикулы, SAP-коды, SKU и т.д. Если в их обозначениях есть логика, то их можно легко вытаскивать из любого текста с помощью регулярных выражений. Например, если мы знаем, что наши артикулы всегда состоят из трех заглавных английских букв, дефиса и последующего трехразрядного числа, то:
Логика работы шаблона тут проста. [A-Z] — означает любые заглавные буквы латиницы. Следующий за ним квантор {3} говорит о том, что нам важно, чтобы таких букв было именно три. После дефиса мы ждем три цифровых разряда, поэтому добавляем на конце d{3}
Денежные суммы
Похожим на предыдущий пункт образом, можно вытаскивать и цены (стоимости, НДС…) из описания товаров. Если денежные суммы, например, указываются через дефис, то:
Паттерн d с квантором + ищет любое число до дефиса, а d{2} будет искать копейки (два разряда) после.
Если нужно вытащить не цены, а НДС, то можно воспользоваться третьим необязательным аргументом нашей функции RegExpExtract, задающим порядковый номер извлекаемого элемента. И, само-собой, можно заменить функцией ПОДСТАВИТЬ (SUBSTITUTE) в результатах дефис на стандартный десятичный разделитель и добавить двойной минус в начале, чтобы Excel интерпретировал найденный НДС как нормальное число:
Автомобильные номера
Если не брать спецтранспорт, прицепы и прочие мотоциклы, то стандартный российский автомобильный номер разбирается по принципу «буква — три цифры — две буквы — код региона». Причем код региона может быть 2- или 3-значным, а в качестве букв применяются только те, что похожи внешне на латиницу. Таким образом, для извлечения номеров из текста нам поможет следующая регулярка:
Время
Для извлечения времени в формате ЧЧ:ММ подойдет такое регулярное выражение:
После двоеточия фрагмент [0-5]d, как легко сообразить, задает любое число в интервале 00-59. Перед двоеточием в скобках работают два шаблона, разделенных логическим ИЛИ (вертикальной чертой):
- [0-1]d — любое число в интервале 00-19
- 2[0-3] — любое число в интервале 20-23
К полученному результату можно применить дополнительно еще и стандартную Excel’евскую функцию ВРЕМЯ (TIME), чтобы преобразовать его в понятный программе и пригодный для дальнейших расчетов формат времени.
Проверка пароля
Предположим, что нам надо проверить список придуманных пользователями паролей на корректность. По нашим правилам, в паролях могут быть только английские буквы (строчные или прописные) и цифры. Пробелы, подчеркивания и другие знаки препинания не допускаются.
Проверку можно организовать с помощью вот такой несложной регулярки:
По сути, таким шаблоном мы требуем, чтобы между началом (^) и концом ($) в нашем тексте находились только символы из заданного в квадратных скобках набора. Если нужно проверить еще и длину пароля (например, не меньше 6 символов), то квантор + можно заменить на интервал «шесть и более» в виде {6,}:
Город из адреса
Допустим, нам нужно вытащить город из строки адреса. Поможет регулярка, извлекающая текст от «г.» до следующей запятой:
Давайте разберем этот шаблон поподробнее.
Если вы прочитали текст выше, то уже поняли, что некоторые символы в регулярных выражениях (точки, звездочки, знаки доллара и т.д.) несут особый смысл. Если же нужно искать сами эти символы, то перед ними ставится обратная косая черта (иногда это называют экранированием). Поэтому при поиске фрагмента «г.» мы должны написать в регулярке г. если ищем плюсик, то + и т.д.
Следующих два символа в нашем шаблоне — точка и звездочка-квантор — обозначают любое количество любых символов, т.е. любое название города.
На конце шаблона стоит запятая, т.к. мы ищем текст от «г.» до запятой. Но ведь в тексте может быть несколько запятых, правда? Не только после города, но и после улицы, дома и т.д. На какой из них будет останавливаться наш запрос? Вот за это отвечает вопросительный знак. Без него наша регулярка вытаскивала бы максимально длинную строку из всех возможных:
В терминах регулярных выражений, такой шаблон является «жадным». Чтобы исправить ситуацию и нужен вопросительный знак — он делает квантор, после которого стоит, «скупым» — и наш запрос берет текст только до первой встречной запятой после «г.»:
Имя файла из полного пути
Еще одна весьма распространенная ситуация — вытащить имя файла из полного пути. Тут поможет простая регулярка вида:
Тут фишка в том, что поиск, по сути, происходит в обратном направлении — от конца к началу, т.к. в конце нашего шаблона стоит $, и мы ищем все, что перед ним до первого справа обратного слэша. Бэкслэш заэкранирован, как и точка в предыдущем примере.
P.S.
«Под занавес» хочу уточнить, что все вышеописанное — это малая часть из всех возможностей, которые предоставляют регулярные выражения. Спецсимволов и правил их использования очень много и на эту тему написаны целые книги (рекомендую для начала хотя бы эту). В некотором смысле, написание регулярных выражений — это почти искусство. Почти всегда придуманную регулярку можно улучшить или дополнить, сделав ее более изящной или способным работать с более широким диапазоном вариантов входных данных.
Для анализа и разбора чужих регулярок или отладки своих собственных есть несколько удобных онлайн-сервисов: RegEx101, RegExr и др.
К сожалению, не все возможности классических регулярных выражений поддерживаются в VBA (например, обратный поиск или POSIX-классы) и умеют работать с кириллицей, но и того, что есть, думаю, хватит на первое время, чтобы вас порадовать.
Если же вы не новичок в теме, и вам есть чем поделиться — оставляйте полезные при работе в Excel регулярки в комментариях ниже. Один ум хорошо, а два сапога — пара!
Ссылки по теме
- Замена и зачистка текста функцией ПОДСТАВИТЬ (SUBSTITUTE)
- Поиск и подсветка символов латиницы в русском тексте
- Поиск ближайшего похожего текста (Иванов = Ивонов = Иваноф и т.д.)
You can use text functions to manipulate text strings in Excel. However, you can’t use them with regular expressions. As of writing this article VBA is your only option. In this guide, we’re going to show you how to use regular expressions in Excel.
Download Workbook
What is a regular expression?
A regular expression (also known as regex or regexp shortly) is a special text string for specifying a search pattern. They are like wildcards. Instead of specifying the number of characters, you can create patterns to find a specific group of characters, like searching between «b» to «o», using OR logic, excluding some characters, or repeating values.
Regular expressions are commonly used for text parsing and replacing operations for all programming languages. To use regular expressions in Excel, we will be using VBA.
Pattern | Description | Samples |
^jack | begins with «jack» | jack-of-all-trades, jack’s house |
jack$ | ends with «jack» | hijack |
^jack$ | is exactly «jack» | jack |
colo[u]{0,}r | can include «u» at least 0 times | colour, color (not colur) |
col[o|u]r | includes either «o» or «u» | color, colur (not colour) |
col[^u]r | accepts any character except «u» | color (not colur or colour) |
How to use regular expressions
Let’s start using regular expressions in Excel by opening VBA. Press Alt + F11 keys to open VBA (Visual Basic for Applications) window. Add a module to enter your code.
Next step is to add regular expression reference to VBA. Click Tools > References in the VBA toolbar. Find and check Microsoft VBScript Regular Expressions 5.5 item in the References window. Click OK to add the reference.
Using the VBScript reference, we can create a regular expression object, which is defined as RegExp in VBA. A RegExp object has 4 properties and 3 methods:
Properties
Name | Type | Description |
Global | Boolean | Set True to find all cases that match with the pattern. Set False to find the first match. |
IgnoreCase | Boolean | Set True to not make case-sensitive search. Set False to make case-sensitive search. |
Multiline | Boolean | Set True if your string has multiple lines and you want to perform the search in all lines. |
Pattern | String | The regular expression pattern you want to search. |
Methods
Name | Arguments | Description |
Execute | sourceString As String | Returns an array that contains all occurrences of the pattern matched in the string. |
Replace | sourceString As String replaceVar As Variant | Returns a string which all occurrences of the pattern in the string are replaced with the replaceVar string. |
Test | sourceString As String | Returns True if there is a match. Otherwise, False. |
Code Samples
A function that returns TRUE/FALSE if the pattern is found in a string
Public Function RegExFind(str As String, pat As String) As Boolean
‘Define the regular expression object
Dim RegEx As New RegExp
‘Set up regular expression properties
With RegEx
.Global = False ‘All occurences are not necessary since a single occurence is enough
.IgnoreCase = True ‘No case-sensitivty
.MultiLine = True ‘Check all lines
.Pattern = pat ‘pattern
End With
RegExFind = RegEx.Test(str)
End Function
After writing the code, you can use this function as a regular Excel function.
A function that replaces the pattern with a given string
Public Function RegExReplace(str As String, pat As String, replaceStr As String) As String
‘Define the regular expression object
Dim RegEx As New RegExp
‘Set up regular expression properties
With RegEx
.Global = False ‘All occurences are not necessary since a single occurence is enough
.IgnoreCase = True ‘No case-sensitivty
.MultiLine = True ‘Check all lines
.Pattern = pat ‘pattern
End With
RegExReplace = RegEx.Replace(str, replaceStr) ‘Return the modified string with replacement value
End Function
The following sample shows how to replace strings that start with «col», continue with 0 or 1 occurrences of «o» and single «u», and finally ends with an «r» character with «Color» string.
In this Article
- What is Regex?
- Matching Characters
- Quantifiers
- Grouping
- How to Use Regex in VBA
- Testing a Pattern for a Match Against a String
- Replacing a Pattern in a String
- Matching and Displaying a Pattern in a String
This tutorial will demonstrate how to use Regex in VBA.
What is Regex?
Regex stands for regular expression. A regular expression is a pattern made up of a sequence of characters that you can use to find a matching pattern in another string. In order to use Regex in VBA you have to use the RegExp object.
A pattern such as [A-C] can be used to search for and match an upper case letter from A to C from a sequence. Regex patterns have their own syntax and can be built using a character or sequence of characters.
Matching Characters
The following table shows the syntax which will allow you to build Regex patterns.
Pattern Syntax | Description | Example | Matches Found |
---|---|---|---|
. | Matches any single character except vbNewLine | f.n | fan, fon, f@n, fwn |
[characters] | Matches any single character between brackets[] | [fn] | Would only match “f” or “n” in fan |
[^characters] | Matches any single character that is not between brackets[] | [^fn] | So would match “j” in “fjn” |
[start-end] | Matches any character that is part of the range in brackets[] | [1-5] | Would match “4” and “5” in “45” |
w | Matches alphanumeric characters and the underscore, but not the space character | w | Would match “c” in “,c.” |
W | Matches any non-alphanumeric characters and the underscore | W | Would match “@” in “bb@bb” |
s | Matches any white space character such as spaces and tabs | s | Would match ” ” in “This is” |
S | Matches any non-white space character | S | Would match “T” and “h” in “T h” |
d | Matches any single decimal digit | d | Would match “7” in “a7h” |
D | Matches any single non-decimal digit | D | Would match j in “47j” |
Escapes special characters which then allows you to search for them | . | Would match “.” in “59.pQ” | |
t | Tab | t | Would match a tab character |
r | Carriage Return | r | Would match a carriage return (vbCr) |
n | vbNewLine(vbTab) | n | Would match a new line |
Quantifiers
You can use quantifiers to specify how many times you want the pattern to match against the string.
Quantifier | Description | Example | Matches Found |
---|---|---|---|
* | Matches zero or more occurrences | fn*a | fna, fa, fnna, fnnna, fnfnnna |
+ | Matches one or more occurrences | fn+a | fna, fnna, fnfnna |
? | Matches zero or one | fn?a | fa, fna |
{n} | Matches “n” many times | dW{4} | Would match “d….” in “d….&5hi” |
{n,} | Matches at least “n” number of times | dW{4,} | Would match “d….&” in “d….&5hi” |
{n,m} | Matches between n and m number of times | dW{1,8} | Would match “d….&&&&” in “d….&&&&5hi” |
Grouping
Grouping or capturing allows you to use a pattern to capture and extract a portion of a string. So not only is the pattern matched, but the part of the string that matches the pattern is captured.
Pattern | Description | Example | Matches Found and Captured |
---|---|---|---|
(expression) | Groups and captures the pattern in parenthesis | (W{4}) | Would group and capture “@@@@” from “1@@@@1jlmba” |
How to Use Regex in VBA
In order to use Regex in VBA, you first have to set the reference in the VBE editor. In the VBE editor, go to Tools > References > Microsoft VBScript Regular Expressions.
These are the properties of the RegExp object:
- Pattern – The pattern you are going to use for matching against the string.
- IgnoreCase – If True, then the matching ignores letter case.
- Global – If True, then all the matches of the pattern in the string are found. If False then only the first match is found.
- MultiLine – If True, pattern matching happens across line breaks.
These are the methods of the RegExp object:
- Test – Searches for a pattern in a string and returns True if a match is found.
- Replace – Replaces the occurrences of the pattern with the replacement string.
- Execute – Returns matches of the pattern against the string.
Testing a Pattern for a Match Against a String
You can use the Test method to check whether a pattern matches a sequence in the input string. The result is True if a match is found. The following code will show you how to test a pattern against a string:
Sub RegexTestingAPattern()
Dim stringOne As String
Dim regexOne As Object
Set regexOne = New RegExp
regexOne.Pattern = "f....a"
stringOne = "000111fjo88a8"
Debug.Print regexOne.Test(stringOne)
End Sub
The result is:
VBA Coding Made Easy
Stop searching for VBA code online. Learn more about AutoMacro — A VBA Code Builder that allows beginners to code procedures from scratch with minimal coding knowledge and with many time-saving features for all users!
Learn More
Replacing a Pattern in a String
You can use the Replace method to replace the first instance of a matching pattern in a string or all the instances of a matching pattern in a string. If Global is set to False, then only the first instance is replaced. The following code will show you how to replace a pattern in a string:
Sub RegexReplacingAPattern()
Dim stringOne As String
Dim regexOne As Object
Set regexOne = New RegExp
regexOne.Pattern = "This is the number"
regexOne.Global = False
stringOne = "This is the number 718901"
Debug.Print regexOne.Replace(stringOne, "That is the new number")
End Sub
The result is:
To replace only the number portion of the string used above, you would use the following code:
Sub RegexReplacingAPattern()
Dim stringOne As String
Dim regexOne As Object
Set regexOne = New RegExp
regexOne.Pattern = "[^D]+"
regexOne.Global = False
stringOne = "This is the number 718901"
Debug.Print regexOne.Replace(stringOne, "777192")
End Sub
The result is:
To replace every instance of a certain pattern in a string, you would set the global value to True. The following code shows you how to replace every instance of -A1289C- in the string:
Sub RegexReplacingEveryInstanceOfAPattern()
Dim stringOne As String
Dim regexOne As Object
Set regexOne = New RegExp
regexOne.Pattern = "WAd+CW"
regexOne.Global = True
stringOne = "ABC-A1289C-ABC-A1289C-ABC"
Debug.Print regexOne.Replace(stringOne, "IJK")
End Sub
Matching and Displaying a Pattern in a String
You can use the Execute method to match one or all instances of a pattern within a string. The following code shows you how to match and display all instances of the pattern from the string:
Sub RegexMatchingAndDisplayingAPattern()
Dim stringOne As String
Dim regexOne As Object
Dim theMatches As Object
Dim Match As Object
Set regexOne = New RegExp
regexOne.Pattern = "A.C"
regexOne.Global = True
regexOne.IgnoreCase = True
stringOne = "ABC-A1289C-ADC-A1289C-AJC"
Set theMatches = regexOne.Execute(stringOne)
For Each Match In theMatches
Debug.Print Match.Value
Next
End Sub
The result is:
Let’s say we only wanted to match -ADC- from the above string. The following code shows how to match and display only -ADC- from the string:
Sub RegexMatchingAndDisplayingAPattern()
Dim stringOne As String
Dim regexOne As Object
Dim theMatches As Object
Dim Match As Object
Set regexOne = New RegExp
regexOne.Pattern = "-A.C-"
regexOne.Global = False
regexOne.IgnoreCase = True
stringOne = "ABC-A1289C-ADC-A1289C-AEC"
Set theMatches = regexOne.Execute(stringOne)
For Each Match In theMatches
Debug.Print Match.Value
Next
End Sub
Regex can take some time to learn, but it’s an extremely powerful tool for identifying/manipulating strings of text. It’s also broadly used across programming languages.