Задача извлечения и стандартизации телефонных номеров из произвольного текстового поля является одной из часто встречающихся в автоматизации бизнес-процессов. Номер телефона может быть написан в самых разнообразных форматах: со скобками, пробелами, дефисами, с префиксом +7, 8 или без него, а также содержать посторонние символы или текстовую информацию. Наша цель – разработать универсальную функцию в 1С, которая сможет выделить корректный российский номер телефона и привести его к единому формату +7xxxyyyzzqq.
Для надежного извлечения и форматирования телефонных номеров из неструктурированного текста необходимо придерживаться многоэтапной стратегии, которая включает очистку, нормализацию и валидацию данных. Рассмотрим основные шаги, которые мы предпримем для решения этой задачи:
+ может быть исключением, если он используется для обозначения международного префикса.
8 на +7 и добавление +7, если номер состоит из 10 цифр и явно не содержит код страны.
Давайте погрузимся в реализацию на платформе 1С, используя встроенные строковые функции. Мы рассмотрим предложенный на форуме пример кода и проанализируем каждый его шаг, чтобы понять, как он справляется с различными вариантами ввода.
Первый и один из самых важных шагов — это извлечение только цифровых символов из исходного текста. Это поможет нам убрать все лишние знаки, такие как пробелы, дефисы, скобки, а также буквенные символы, которые могут быть ошибочно введены вместо цифр (например, l вместо 1 или O вместо 0).
Мы будем перебирать каждый символ исходной строки и добавлять его к новой, очищенной строке, только если этот символ является цифрой. Вот как это можно реализовать:
ОтформатированныйТекст = "";
Для Ш = 1 По СтрДлина(Текст) Цикл
Цифра = Сред(Текст,Ш,1);
Если СтрНайти("0123456789",Цифра) Тогда
ОтформатированныйТекст = ОтформатированныйТекст + Цифра;
КонецЕсли;
КонецЦикла;
После выполнения этого блока кода, переменная ОтформатированныйТекст будет содержать только цифры из исходного номера. Например, если исходный текст был "Вася 8912 123-4560", то ОтформатированныйТекст станет "89121234560".
Затем, чтобы предотвратить слишком длинные номера и подготовить строку к дальнейшей обработке, мы можем обрезать или дополнить ее до определенной длины, например, 15 символов (с запасом для +7 и 10 цифр):
ОтформатированныйТекст = Лев(ОтформатированныйТекст + "##########",15);
Здесь "##########" используется как "заполнитель", чтобы гарантировать, что строка будет иметь минимальную длину для последующих операций, даже если входных цифр было очень мало. Метод Лев() обрезает строку, если она длиннее 15 символов.
Российские номера телефонов часто начинаются с 7 или 8. Наша задача — привести их к единому международному формату, начинающемуся с +7. Мы проверим первую цифру очищенного номера и, если она равна 7 или 8, удалим ее, чтобы затем добавить +7 в начале.
ПерваяЦифра = Лев(ОтформатированныйТекст,1);
Если ПерваяЦифра = "7" ИЛИ ПерваяЦифра = "8" Тогда
ОтформатированныйТекст = Сред(ОтформатированныйТекст,2);
КонецЕсли;
После этого шага, если номер был "89121234560" или "79121234560", он станет "9121234560". Это позволяет нам единообразно добавлять +7 в финальном форматировании.
Теперь, когда у нас есть 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-объекты или внешние компоненты, которые предоставляют функциональность регулярных выражений.
Основное преимущество регулярных выражений заключается в их способности гибко описывать шаблоны поиска. Например, для российского номера телефона мы могли бы использовать шаблон, который учитывает:
+ (опционально).7 или 8.(), пробелы , дефисы - как разделители (опционально).Пример такого (обобщенного, не 1С) регулярного выражения мог бы выглядеть так: ^(\+7|8)?[\s\-]?\(?\d{3}\)?[\s\-]?\d{3}[\s\-]?\d{2}[\s\-]?\d{2}$. После извлечения номера с помощью такого шаблона, потребуется дополнительная очистка от всех нецифровых символов и приведение к формату +7xxxyyyzzqq, как мы делали выше.
Использование регулярных выражений позволяет нам:
+ в начале).
Мы выяснили, что даже при использовании продвинутых методов, существуют сценарии, требующие особого внимания:
l (латинская L) вместо 1 (единицы), или O (латинская O) вместо 0 (нуля). Наш текущий код их просто проигнорирует. Для повышения надежности, можно добавить шаг замены таких символов перед основной очисткой (например, СтрЗаменить(Текст, "l", "1")).
+7, не сможет корректно обработать такие номера. В этом случае мы можем применить следующие подходы:
+380 для Украины, +370 для Литвы и т.д.) и соответствующие длины номеров.
libphonenumber от Google. Она позволяет не только извлечь номер из текста, но и автоматически определить страну, тип номера (мобильный, городской, бесплатный) и привести его к стандартному международному формату E.164 (например, +79121234560). Для использования такой библиотеки в 1С потребуется либо интеграция через COM-объекты, либо вызов внешних сервисов/обработок.
libphonenumber будут более эффективны.
Мы рассмотрели, как можно эффективно извлечь и привести телефонный номер к единому формату +7xxxyyyzzqq в 1С. Основной подход включает последовательную очистку от лишних символов, стандартизацию префиксов (8 на +7) и форматирование оставшихся цифр. Представленный код на 1С демонстрирует практическую реализацию этих шагов, подходящую для динамической обработки ввода на форме.
Для более сложных сценариев, таких как обработка нескольких номеров в одном тексте, распознавание международных номеров или номера с добавочными, мы рекомендовали рассмотреть применение регулярных выражений (через COM-объекты) или специализированных библиотек, таких как libphonenumber. Выбор конкретного метода зависит от требований к надежности, гибкости и масштабам обрабатываемых данных.