В процессе разработки часто возникает задача нормализации данных, вводимых пользователем. Типичный пример — поиск контрагента по номеру телефона. Менеджеры могут вводить номер в удобном им виде: со скобками, тире, пробелами или международным префиксом +7. Однако в базе данных номера зачастую хранятся в строгом цифровом формате (например, 10 знаков без разделителей). Если не привести поисковый запрос к формату хранения, поиск не даст результатов.
В этой статье мы подробно разберем несколько подходов к решению этой задачи: от простых циклов до использования регулярных выражений и встроенных функций БСП. Мы проанализируем ситуацию, когда нужно получить ровно 10 цифр номера, и выясним причину возможных ошибок при обработке префиксов 8 и +7.
Это самый надежный и понятный способ, который работает на любой версии платформы 1С. Мы пройдемся по каждому символу исходной строки и проверим, является ли он цифрой. Рассмотрим этот алгоритм подробнее.
Логика проста: создаем пустую строку-аккумулятор, перебираем входные данные и, если символ входит в диапазон от "0" до "9", добавляем его к результату. Посмотрим на пример кода:
// Допустим, переменная СтрокаПоиска содержит "8(900) 123-45-67"
ДлинаСтроки = СтрДлина(СтрокаПоиска);
ОчищенныйНомер = "";
Для Сч = 1 По ДлинаСтроки Цикл
Символ = Сред(СтрокаПоиска, Сч, 1);
// Проверяем, является ли символ цифрой
Если Символ >= "0" И Символ <= "9" Тогда
ОчищенныйНомер = ОчищенныйНомер + Символ;
КонецЕсли;
КонецЦикла;
// На выходе получим "89001234567"
Этот метод хорош тем, что нам не нужно заранее знать, какие именно лишние символы ввел пользователь (пробелы, знаки решетки, буквы или спецсимволы). Мы просто игнорируем всё, что не является цифрой.
Если мы заранее знаем список символов-разделителей, которые могут встретиться, мы можем воспользоваться функцией СтрЗаменить. Это выглядит проще в написании, но требует перечисления всех возможных вариантов.
Проанализируем пример реализации:
Результат = СтрокаПоиска;
Результат = СтрЗаменить(Результат, "+", "");
Результат = СтрЗаменить(Результат, "-", "");
Результат = СтрЗаменить(Результат, "(", "");
Результат = СтрЗаменить(Результат, ")", "");
Результат = СтрЗаменить(Результат, " ", "");
// И так далее для всех возможных знаков
Важный нюанс: основной недостаток этого метода заключается в том, что если пользователь введет какой-то редкий символ (например, точку или квадратную скобку), он останется в строке и поиск завершится неудачей. Поэтому первый способ с перебором символов считается более универсальным.
После того как мы очистили номер от лишних символов, мы часто получаем 11 цифр (если номер начинался с 8 или 7), в то время как в базе может храниться только 10 цифр кода города и самого номера. Разберем, как правильно "отрезать" лишнее.
Наиболее простой и эффективный способ получить последние 10 знаков — использовать функцию Прав(). Это позволит корректно обработать и номера, начинающиеся на +7, и номера на 8, и даже номера, введенные сразу без кода страны.
Посмотрим на код с учетом этой логики:
// Очищаем номер (используем метод из Способа 1)
ЧистыйНомер = ОчиститьОтСимволов(СтрокаПоиска);
// Берем только 10 знаков справа
Если СтрДлина(ЧистыйНомер) >= 10 Тогда
КонечныйРезультат = Прав(ЧистыйНомер, 10);
Иначе
Предупреждение("Номер введен некорректно, слишком мало цифр!");
КонецЕсли;
Такой подход гарантирует, что мы всегда будем искать по шаблону 9001234567, независимо от того, ввел ли пользователь +7... или 8....
В новых версиях платформы 8.3 (начиная с 8.3.10) появились мощные функции для работы со строками, позволяющие реализовывать различные алгоритмы разбора текста. Мы можем "инвертировать" задачу: сначала найти все нецифровые символы, а затем использовать их как разделители.
Рассмотрим такой элегантный пример:
// Определяем строку со всеми цифрами
Цифры = "0123456789";
// Получаем строку из всех символов, которые НЕ являются цифрами
ЛишниеСимволы = СтрСоединить(СтрРазделить(ИсходнаяСтрока, Цифры), "");
// Используем эти символы как разделители, чтобы "вытащить" только цифры
МассивЧастей = СтрРазделить(ИсходнаяСтрока, ЛишниеСимволы, Ложь);
Результат = СтрСоединить(МассивЧастей, "");
Этот метод работает очень быстро на больших объемах данных, так как платформенные методы СтрРазделить оптимизированы лучше, чем циклы Для...По.
Для профессиональной разработки часто применяются регулярные выражения, для которых существуют инструменты тестирования прямо в 1С. Это позволяет очистить строку буквально одной командой. В среде Windows для этого используется объект VBScript.RegExp.
Разберем по шагам, как это работает:
VBScript.RegExp через Новый COMОбъект.[^\d] (означает "всё, что не является цифрой").Replace, заменяя всё найденное на пустую строку.
RegExp = Новый COMОбъект("VBScript.RegExp");
RegExp.IgnoreCase = Истина;
RegExp.Global = Истина;
RegExp.MultiLine = Истина;
RegExp.Pattern = "[^\d]"; // Ищем всё, кроме цифр
ОчищенныйНомер = RegExp.Replace(СтрокаПоиска, "");
Результат = Прав(ОчищенныйНомер, 10);
Важно: этот метод будет работать только на серверах под управлением ОС Windows. Если ваш сервер 1С работает на Linux, данный COM-объект будет недоступен.
Если вы работаете в современной конфигурации (например, УТ 11, БП 3.0, ERP), то в ней, скорее всего, уже встроена БСП. Разработчики 1С уже написали все необходимые функции за нас. Проанализируем возможности общего модуля РаботаСНомерамиТелефонов.
Вам достаточно вызвать готовую функцию:
// Пример для БСП
ОчищенныйНомер = РаботаСНомерамиТелефонов.ОчиститьТекстНомераТелефона(СтрокаПоиска);
Функции БСП хороши тем, что они учитывают множество нюансов: международные префиксы, добавочные номера (внутренние телефоны) и требования законодательства разных стран. Если конфигурация позволяет, всегда делайте выбор в пользу типовых механизмов.
Мы рассмотрели различные ситуации и способы их решения. Подведем итоги того, как лучше организовать поиск по телефону:
Прав(..., 10).Применяя эти подходы, вы обеспечите удобство работы менеджеров, так как они смогут вставлять номера из любых источников, не заботясь о правильности расстановки скобок и тире.