Содержание
У меня в таблице есть примерно такие записи:
Мне необходимо сделать поиск-замена и поставить пробел после знака № , чтобы все были одинаковы. Это, как мне кажется, надо реализовать с помощью регулярных выражений.
Как правильно задать такое регулярное выражение для поиска строк, где после № идет символ, не равный пробелу?
1 ответ 1
Может быть, проще?
Выделить диапазон данных, НАЙТИ-№-ЗАМЕНИТЬ-№ (номер с пробелом)-ОК;
НАЙТИ — (два пробела)-ЗАМЕНИТЬ— (один пробел)-ОК
Регулярные выражение (Regular Expressions, RegExp) – это мощный инструмент для обработки текстовых данных, позволяющий осуществлять поиск и выполнять манипуляции с подстроками в тексте. По сути, регулярное выражение является шаблоном текста, состоящим из обычных и специальных символов. Excel не позволяет использовать всю мощь регулярных выражений на пользовательском уровне, но язык VBA, на котором создаются макросы в Excel, предоставляет такую возможность. Данный вебинар посвящен тому, как при помощи элементов языка VBA (оператора VBA Like и объекта RegExp) освоить процесс создания регулярных выражений в «Экселе».
Занятие проведёт замечательный преподаватель-практик с многосторонним опытом работы Ожиганов Сергей Иванович. Сертифицированный тренер Microsoft, обладатель статуса MCTS (Managing Projects With Microsoft Project 2013) и ряда других престижных сертификацией корпорации «Майкрософт». Виртуозно владея «Экселем», он решает реальные практические задачи, связанные со сложным анализом данных и оптимизацией работы. Участвует в разработке программного обеспечения, ежедневно оказывает услуги консалтинга по продуктам «Майрософт» и отлично понимает, какие вопросы могут возникнуть у слушателей. Сергей Иванович прекрасно умеет объяснять материал с позиции практика, не оставляя ни одной сложной темы без конкретных примеров. Среди его выпускников – специалисты крупнейших российских и международных компаний, включая ООО «МЕТРО Кэш энд Керри», ОАО «Вымпелком», ООО «Газпром-Медиа» и др.
Ближайшие группы Сортировать:
Заказ добавлен в Корзину.
Для завершения оформления, пожалуйста, перейдите в Корзину!
Одной из самых трудоемких и неприятных задач при работе с текстом в 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 и скопируйте туда текст вот такой макрофункции:
Теперь можно закрыть редактор 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 ) будет искать в тексте любое из указанных слов. Обычно набор вариантов заключается в скобки. |
^ | Начало строки |
$ | Конец строки |
Край слова |
Если мы ищем определенное количество символов, например, шестизначный почтовый индекс или все трехбуквенные коды товаров, то на помощь нам приходят квантификаторы или кванторы — специальные выражения, задающие количество искомых знаков. Квантификаторы применяются к тому символу, что стоит перед ним:
Квантор | Описание |
? | Ноль или одно вхождение. Например .? будет означать один любой символ или его отсутствие. |
+ | Одно или более вхождений. Например d+ означает любое количество цифр (т.е. любое число от 0 до бесконечности). |
* | Ноль или более вхождений, т.е. любое количество. Так s* означает любое количество пробелов или их отсутствие. |
<число > или <число1 , число2 > |
Если нужно задать строго определенное количество вхождений, то оно задается в фигурных скобках. Например d означает строго шесть цифр, а шаблон s<2,5 > — от двух до пяти пробелов |
Теперь давайте перейдем к самому интересному — разбору применения созданной функции и того, что узнали о паттернах на практических примерах из жизни.
Извлекаем числа из текста
Для начала разберем простой случай — нужно извлечь из буквенно-цифровой каши первое число, например мощность источников бесперебойного питания из прайс-листа:
Логика работы регулярного выражения тут простая: d — означает любую цифру, а квантор + говорит о том, что их количество должно быть одна или больше. Двойной минус перед функцией нужен, чтобы "на лету" преобразовать извлеченные символы в полноценное число из числа-как-текст.
Почтовый индекс
На первый взгляд, тут все просто — ищем ровно шесть цифр подряд. Используем спецсимвол d для цифры и квантор для количества знаков:
Однако, возможна ситуация, когда левее индекса в строке стоит еще один большой набор цифр подряд (номер телефона, ИНН, банковский счет и т.д.) Тогда наша регулярка выдернет из нее первых 6 цифр, т.е. сработает некорректно:
Чтобы этого не происходило, необходимо добавить в наше регулярное выражение по краям модификатор означающий конец слова. Это даст понять Excel, что нужный нам фрагмент (индекс) должен быть отдельным словом, а не частью другого фрагмента (номера телефона):
Телефон
Проблема с нахождением телефонного номера среди текста состоит в том, что существует очень много вариантов записи номеров — с дефисами и без, через пробелы, с кодом региона в скобках или без и т.д. Поэтому, на мой взгляд, проще сначала вычистить из исходного текста все эти символы с помощью нескольких вложенных друг в друга функций ПОДСТАВИТЬ (SUBSTITUTE) , чтобы он склеился в единое целое, а потом уже примитивной регуляркой d вытаскивать 11 цифр подряд:
Тут чуть сложнее, т.к. ИНН (в России) бывает 10-значный (у юрлиц) или 12-значный (у физлиц). Если не придираться особо, то вполне можно удовлетвориться регуляркой d , но она, строго говоря, будет вытаскивать все числа от 10 до 12 знаков, т.е. и ошибочно введенные 11-значные. Правильнее будет использовать два шаблона, связанных логическим ИЛИ оператором | (вертикальная черта):
Обратите внимание, что в запросе мы сначала ищем 12-разрядные, и только потом 10-разрядные числа. Если же записать нашу регулярку наоборот, то она будет вытаскивать для всех, даже длинных 12-разрядных ИНН, только первые 10 символов. То есть после срабатывания первого условия дальнейшая проверка уже не производится:
Это принципиальное отличие оператора | от стандартной экселевской логической функции ИЛИ (OR) , где от перестановки аргументов результат не меняется.
Артикулы товаров
Во многих компаниях товарам и услугам присваиваются уникальные идентификаторы — артикулы, SAP-коды, SKU и т.д. Если в их обозначениях есть логика, то их можно легко вытаскивать из любого текста с помощью регулярных выражений. Например, если мы знаем, что наши артикулы всегда состоят из трех заглавных английских букв, дефиса и последующего трехразрядного числа, то:
Логика работы шаблона тут проста. [A-Z] — означает любые заглавные буквы латиницы. Следующий за ним квантор говорит о том, что нам важно, чтобы таких букв было именно три. После дефиса мы ждем три цифровых разряда, поэтому добавляем на конце d
Денежные суммы
Похожим на предыдущий пункт образом, можно вытаскивать и цены (стоимости, НДС. ) из описания товаров. Если денежные суммы, например, указываются через дефис, то:
Паттерн d с квантором + ищет любое число до дефиса, а d будет искать копейки (два разряда) после.
Если нужно вытащить не цены, а НДС, то можно воспользоваться третьим необязательным аргументом нашей функции RegExpExtract, задающим порядковый номер извлекаемого элемента. И, само-собой, можно заменить функцией ПОДСТАВИТЬ (SUBSTITUTE) в результатах дефис на стандартный десятичный разделитель и добавить двойной минус в начале, чтобы Excel интерпретировал найденный НДС как нормальное число:
Автомобильные номера
Если не брать спецтранспорт, прицепы и прочие мотоциклы, то стандартный российский автомобильный номер разбирается по принципу "буква — три цифры — две буквы — код региона". Причем код региона может быть 2- или 3-значным, а в качестве букв применяются только те, что похожи внешне на латиницу. Таким образом, для извлечения номеров из текста нам поможет следующая регулярка:
Время
Для извлечения времени в формате ЧЧ:ММ подойдет такое регулярное выражение:
После двоеточия фрагмент [0-5]d , как легко сообразить, задает любое число в интервале 00-59. Перед двоеточием в скобках работают два шаблона, разделенных логическим ИЛИ (вертикальной чертой):
- [0-1]d — любое число в интервале 00-19
- 2[0-3] — любое число в интервале 20-23
К полученному результату можно применить дополнительно еще и стандартную Excel’евскую функцию ВРЕМЯ (TIME) , чтобы преобразовать его в понятный программе и пригодный для дальнейших расчетов формат времени.
Проверка пароля
Предположим, что нам надо проверить список придуманных пользователями паролей на корректность. По нашим правилам, в паролях могут быть только английские буквы (строчные или прописные) и цифры. Пробелы, подчеркивания и другие знаки препинания не допускаются.
Проверку можно организовать с помощью вот такой несложной регулярки:
По сути, таким шаблоном мы требуем, чтобы между началом ( ^ ) и концом ( $ ) в нашем тексте находились только символы из заданного в квадратных скобках набора. Если нужно проверить еще и длину пароля (например, не меньше 6 символов), то квантор + можно заменить на интервал "шесть и более" в виде :
Город из адреса
Допустим, нам нужно вытащить город из строки адреса. Поможет регулярка, извлекающая текст от "г." до следующей запятой:
Давайте разберем этот шаблон поподробнее.
Если вы прочитали текст выше, то уже поняли, что некоторые символы в регулярных выражениях (точки, звездочки, знаки доллара и т.д.) несут особый смысл. Если же нужно искать сами эти символы, то перед ними ставится обратная косая черта (иногда это называют экранированием). Поэтому при поиске фрагмента "г." мы должны написать в регулярке г. если ищем плюсик, то + и т.д.
Следующих два символа в нашем шаблоне — точка и звездочка-квантор — обозначают любое количество любых символов, т.е. любое название города.
На конце шаблона стоит запятая, т.к. мы ищем текст от "г." до запятой. Но ведь в тексте может быть несколько запятых, правда? Не только после города, но и после улицы, дома и т.д. На какой из них будет останавливаться наш запрос? Вот за это отвечает вопросительный знак. Без него наша регулярка вытаскивала бы максимально длинную строку из всех возможных:
В терминах регулярных выражений, такой шаблон является "жадным". Чтобы исправить ситуацию и нужен вопросительный знак — он делает квантор, после которого стоит, "скупым" — и наш запрос берет текст только до первой встречной запятой после "г.":
Имя файла из полного пути
Еще одна весьма распространенная ситуация — вытащить имя файла из полного пути. Тут поможет простая регулярка вида:
Тут фишка в том, что поиск, по сути, происходит в обратном направлении — от конца к началу, т.к. в конце нашего шаблона стоит $ , и мы ищем все, что перед ним до первого справа обратного слэша. Бэкслэш заэкранирован, как и точка в предыдущем примере.
"Под занавес" хочу уточнить, что все вышеописанное — это малая часть из всех возможностей, которые предоставляют регулярные выражения. Спецсимволов и правил их использования очень много и на эту тему написаны целые книги (рекомендую для начала хотя бы эту). В некотором смысле, написание регулярных выражений — это почти искусство. Почти всегда придуманную регулярку можно улучшить или дополнить, сделав ее более изящной или способным работать с более широким диапазоном вариантов входных данных.
Для анализа и разбора чужих регулярок или отладки своих собственных есть несколько удобных онлайн-сервисов: RegEx101, RegExr и др.
К сожалению, не все возможности классических регулярных выражений поддерживаются в VBA (например, обратный поиск или POSIX-классы) и умеют работать с кириллицей, но и того, что есть, думаю, хватит на первое время, чтобы вас порадовать.
Если же вы не новичок в теме, и вам есть чем поделиться — оставляйте полезные при работе в Excel регулярки в комментариях ниже. Один ум хорошо, а два сапога — пара!