Как извлечь и привести номер телефона из текста к формату +7xxxyyyzzqq в 1С?

Программист 1С v8.3 (Управляемые формы)
← На главную

Задача извлечения и стандартизации телефонных номеров из произвольного текстового поля является одной из часто встречающихся в автоматизации бизнес-процессов. Номер телефона может быть написан в самых разнообразных форматах: со скобками, пробелами, дефисами, с префиксом +7, 8 или без него, а также содержать посторонние символы или текстовую информацию. Наша цель – разработать универсальную функцию в 1С, которая сможет выделить корректный российский номер телефона и привести его к единому формату +7xxxyyyzzqq.

Общая стратегия обработки телефонных номеров

Для надежного извлечения и форматирования телефонных номеров из неструктурированного текста необходимо придерживаться многоэтапной стратегии, которая включает очистку, нормализацию и валидацию данных. Рассмотрим основные шаги, которые мы предпримем для решения этой задачи:

  1. Предварительная очистка данных: На этом этапе мы удалим все символы, которые не являются цифрами, из исходной строки. Это поможет избавиться от пробелов, скобок, дефисов, а также любых буквенных или специальных символов, которые могут быть ошибочно введены. Знак + может быть исключением, если он используется для обозначения международного префикса.
  2. Приведение/разбор по типовым шаблонам: После очистки у нас останется последовательность цифр. Далее мы проанализируем эту последовательность, чтобы определить ее структуру и привести к стандартному виду. Это может включать замену префикса 8 на +7 и добавление +7, если номер состоит из 10 цифр и явно не содержит код страны.
  3. Валидация длины и формата: Мы проверим, соответствует ли полученная числовая последовательность стандартной длине российского телефонного номера (10 цифр после кода страны). Также можно выполнить проверку по известным кодам операторов связи, чтобы убедиться в корректности номера.

Детальный разбор с функциями 1С

Давайте погрузимся в реализацию на платформе 1С, используя встроенные строковые функции. Мы рассмотрим предложенный на форуме пример кода и проанализируем каждый его шаг, чтобы понять, как он справляется с различными вариантами ввода.

Шаг 1: Очистка текста от нецифровых символов

Первый и один из самых важных шагов — это извлечение только цифровых символов из исходного текста. Это поможет нам убрать все лишние знаки, такие как пробелы, дефисы, скобки, а также буквенные символы, которые могут быть ошибочно введены вместо цифр (например, l вместо 1 или O вместо 0).

Мы будем перебирать каждый символ исходной строки и добавлять его к новой, очищенной строке, только если этот символ является цифрой. Вот как это можно реализовать:


ОтформатированныйТекст = "";
Для Ш = 1 По СтрДлина(Текст) Цикл
    Цифра = Сред(Текст,Ш,1);
    Если СтрНайти("0123456789",Цифра) Тогда
        ОтформатированныйТекст = ОтформатированныйТекст + Цифра;    
    КонецЕсли;
КонецЦикла;

После выполнения этого блока кода, переменная ОтформатированныйТекст будет содержать только цифры из исходного номера. Например, если исходный текст был "Вася 8912 123-4560", то ОтформатированныйТекст станет "89121234560".

Затем, чтобы предотвратить слишком длинные номера и подготовить строку к дальнейшей обработке, мы можем обрезать или дополнить ее до определенной длины, например, 15 символов (с запасом для +7 и 10 цифр):

ОтформатированныйТекст = Лев(ОтформатированныйТекст + "##########",15);

Здесь "##########" используется как "заполнитель", чтобы гарантировать, что строка будет иметь минимальную длину для последующих операций, даже если входных цифр было очень мало. Метод Лев() обрезает строку, если она длиннее 15 символов.

Шаг 2: Стандартизация префикса номера

Российские номера телефонов часто начинаются с 7 или 8. Наша задача — привести их к единому международному формату, начинающемуся с +7. Мы проверим первую цифру очищенного номера и, если она равна 7 или 8, удалим ее, чтобы затем добавить +7 в начале.


ПерваяЦифра = Лев(ОтформатированныйТекст,1);
Если ПерваяЦифра = "7" ИЛИ ПерваяЦифра = "8" Тогда
    ОтформатированныйТекст = Сред(ОтформатированныйТекст,2);    
КонецЕсли;

После этого шага, если номер был "89121234560" или "79121234560", он станет "9121234560". Это позволяет нам единообразно добавлять +7 в финальном форматировании.

Шаг 3: Валидация кода оператора и форматирование групп цифр

Теперь, когда у нас есть 10 цифр номера (без префикса страны), мы можем разделить их на группы и, при необходимости, выполнить дополнительную валидацию. В примере кода на форуме используется проверка по списку известных кодов операторов.

Мы определяем список кодов операторов мобильной связи и проверяем, входит ли первые три цифры нашего номера в этот список. Если нет, то мы помечаем код оператора как "###", что позже поможет нам определить, что номер некорректен.


КодыОператоров = "900 901 902 903 904 905 906 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 936 937 938 939 941 950 951 952 953 954 955 956 958 960 961 962 963 964 965 966 967 968 969 970 971 977 978 980 981 982 983 984 985 986 987 988 989 991 992 993 994 995 996 997 999";

КодОператора = Лев(ОтформатированныйТекст,3);

Если СтрНайти(КодыОператоров,КодОператора) Тогда
    КодОператора = Лев(КодОператора + "###",3);
Иначе
    КодОператора = "###";
КонецЕсли;

Обратите внимание, что строка КодОператора = Лев(КодОператора + "###",3); в этом контексте не имеет особого смысла, так как КодОператора уже содержит 3 символа, и добавление "###" с последующим обрезанием до 3 символов не изменит его. Вероятно, это остаток от предыдущих итераций кода или попытка обработки коротких номеров, которая не доведена до конца. Логичнее было бы использовать КодОператора = Лев(ОтформатированныйТекст,3); без изменения, если проверка прошла успешно. Однако, мы оставляем код как есть, согласно предоставленному примеру.

Далее мы извлекаем остальные группы цифр: три цифры после кода оператора, затем две и ещё две. Это соответствует стандартному российскому формату (ХХХ) ХХХ-ХХ-ХХ.


Группа2 = Сред(ОтформатированныйТекст,4,3);    
Группа3 = Сред(ОтформатированныйТекст,7,2);
Группа4 = Сред(ОтформатированныйТекст,9,2);

Теперь мы можем собрать отформатированный номер. В примере кода форматирование происходит в виде +7 XXX XXX XX XX, а затем номер без пробелов сохраняется в отдельной переменной для дальнейшего использования.


ОтформатированныйНомерТелефона = "+7 " + КодОператора + " " + Группа2 + " " + Группа3 + " " + Группа4;
НомерТелефонаПациента = КодОператора + Группа2 + Группа3 + Группа4; 

В случае, если какая-либо часть номера оказалась короче ожидаемой, в соответствующей группе могут появиться символы #, введенные нами на первом шаге. Проверка на наличие # позволяет определить, полностью ли номер сформирован и является ли он корректным.


Если СтрНайти(ОтформатированныйНомерТелефона,"#") Тогда
    // Номер не корректен или не полностью введен
    // ... логика обработки некорректного номера
Иначе 
    // Номер корректен
    // ... логика обработки корректного номера
КонецЕсли;

Важно отметить: данный пример кода является клиентским и, судя по названиям переменных Элементы.СтраницыОтформатированныйНомерТелефона, предназначен для динамического форматирования поля ввода на форме. Для использования в серверном коде или общей функции, часть, относящуюся к элементам формы, необходимо будет адаптировать.

Применение регулярных выражений

Хотя представленный выше код успешно справляется с очисткой и базовым форматированием, для более сложных случаев, особенно с разнообразными паттернами ввода или необходимостью извлечения нескольких номеров из одного текста, регулярные выражения являются мощным инструментом. В 1С нет встроенной полноценной поддержки регулярных выражений для строковых операций, как, например, в Python или Java. Однако, мы можем использовать COM-объекты или внешние компоненты, которые предоставляют функциональность регулярных выражений.

Основное преимущество регулярных выражений заключается в их способности гибко описывать шаблоны поиска. Например, для российского номера телефона мы могли бы использовать шаблон, который учитывает:

  1. Начальный символ + (опционально).
  2. Код страны 7 или 8.
  3. Скобки (), пробелы , дефисы - как разделители (опционально).
  4. 10 цифр основного номера.

Пример такого (обобщенного, не 1С) регулярного выражения мог бы выглядеть так: ^(\+7|8)?[\s\-]?\(?\d{3}\)?[\s\-]?\d{3}[\s\-]?\d{2}[\s\-]?\d{2}$. После извлечения номера с помощью такого шаблона, потребуется дополнительная очистка от всех нецифровых символов и приведение к формату +7xxxyyyzzqq, как мы делали выше.

Использование регулярных выражений позволяет нам:

Работа со сложными случаями и ограничениями

Мы выяснили, что даже при использовании продвинутых методов, существуют сценарии, требующие особого внимания:

  1. Несколько номеров в одной строке: Исходный текст может содержать два или более номера, например, "Вася 89121234560-89091234567". В таких случаях наш текущий алгоритм извлечет только первую последовательность или некорректно склеит цифры. Потребуется более сложное регулярное выражение или итеративный подход, который будет находить и обрабатывать каждый номер по отдельности.
  2. Символы, похожие на цифры: Как было упомянуто, пользователи могут ошибочно вводить буквы l (латинская L) вместо 1 (единицы), или O (латинская O) вместо 0 (нуля). Наш текущий код их просто проигнорирует. Для повышения надежности, можно добавить шаг замены таких символов перед основной очисткой (например, СтрЗаменить(Текст, "l", "1")).
  3. Международные номера: Если в базе могут появиться клиенты из других стран (например, Украины, Прибалтики), наш текущий алгоритм, заточенный под российский формат +7, не сможет корректно обработать такие номера. В этом случае мы можем применить следующие подходы:
    • Расширение валидации: Добавить проверку на другие коды стран (+380 для Украины, +370 для Литвы и т.д.) и соответствующие длины номеров.
    • Использование специализированных библиотек: Одним из наиболее полных и надежных решений для разбора, форматирования и проверки международных телефонных номеров является библиотека libphonenumber от Google. Она позволяет не только извлечь номер из текста, но и автоматически определить страну, тип номера (мобильный, городской, бесплатный) и привести его к стандартному международному формату E.164 (например, +79121234560). Для использования такой библиотеки в 1С потребуется либо интеграция через COM-объекты, либо вызов внешних сервисов/обработок.
  4. Добавочные номера: Если номер содержит добавочный (например, "89121234560 доб. 123"), текущий алгоритм проигнорирует добавочный. Потребуется отдельная логика для извлечения и сохранения добавочного номера в отдельное поле или специальном формате.
  5. Номера, встроенные в другой текст: Например, "ТД Рога и копыта 2000-89121234560". В таких случаях регулярные выражения с более точными границами поиска или библиотеки типа libphonenumber будут более эффективны.

Заключение

Мы рассмотрели, как можно эффективно извлечь и привести телефонный номер к единому формату +7xxxyyyzzqq в 1С. Основной подход включает последовательную очистку от лишних символов, стандартизацию префиксов (8 на +7) и форматирование оставшихся цифр. Представленный код на 1С демонстрирует практическую реализацию этих шагов, подходящую для динамической обработки ввода на форме.

Для более сложных сценариев, таких как обработка нескольких номеров в одном тексте, распознавание международных номеров или номера с добавочными, мы рекомендовали рассмотреть применение регулярных выражений (через COM-объекты) или специализированных библиотек, таких как libphonenumber. Выбор конкретного метода зависит от требований к надежности, гибкости и масштабам обрабатываемых данных.

← На главную