В процессе автоматизации учета часто возникает задача разбора «грязных» данных, в частности — выделения почтового индекса из строки адреса, записанной в свободном формате. Почтовый индекс в России представляет собой шестизначное число, и на первый взгляд задача кажется простой. Однако при реализации программист сталкивается с массой нюансов: индекс может быть в начале, в середине или в конце строки, он может быть слит с другими цифрами или соседствовать с номерами телефонов. Рассмотрим подробнее несколько способов решения этой задачи, от простых алгоритмов до современных инструментов платформы 1С.
Один из самых эффективных и лаконичных способов — применение регулярных выражений. В классических решениях на платформе 1С для этого часто используется объект VBScript.RegExp. Разберем по шагам, как реализовать этот метод.
Основная идея заключается в поиске шаблона, состоящего из шести цифр подряд. Проанализируем пример кода:
Функция ПолучитьИндексНаСервере(Представление)
ПочтовыйИндекс = "";
// Создаем объект для работы с регулярными выражениями
RegExp = Новый COMОбъект("VBScript.RegExp");
// Задаем паттерн: ровно 6 цифр
RegExp.Pattern = "\d{6}";
Matches = RegExp.Execute(Представление);
Если Matches.Count > 0 Тогда
// Берем первое найденное совпадение
Match = Matches.Item(0);
ПочтовыйИндекс = Match.Value;
КонецЕсли;
Возврат ПочтовыйИндекс;
КонецФункции
Важное замечание: При использовании шаблона \d{6} (или \d\d\d\d\d\d) программа может найти первые шесть цифр в длинном номере счета (например, из 20 цифр) или в номере телефона. Чтобы избежать таких ошибок, рекомендуется использовать границы слова. Для этого в регулярных выражениях используется символ \b. Обновленный паттерн будет выглядеть так: \b\d{6}\b. Это гарантирует, что мы найдем именно отдельно стоящее шестизначное число.
Если вы работаете на современных версиях платформы (8.3.23 и выше), использование COMОбъект становится избыточным и даже вредным, особенно для серверов на базе Linux. Теперь в 1С есть встроенный объект РегулярноеВыражение. Рассмотрим, как переписать нашу задачу под новые стандарты.
Посмотрим на пример реализации:
Функция ВыделитьИндексНативно(СтрокаАдреса)
// Используем границы слова \b для исключения попадания в длинные числа
Паттерн = "\b\d{6}\b";
РегВыр = Новый РегулярноеВыражение(Паттерн);
Результат = РегВыр.Найти(СтрокаАдреса);
Если Результат <> Неопределено Тогда
Возврат Результат.Значение;
КонецЕсли;
Возврат "";
КонецФункции
Этот метод работает значительно быстрее, чем вызов через COM, и является кроссплатформенным. Проанализируем ситуацию: если индекс в адресе записан слитно с номером дома (например, "ул.Ленина12-14362000"), граница слова \b может не сработать. В таких случаях паттерн приходится усложнять или комбинировать с другими методами очистки строки.
Если по каким-то причинам регулярные выражения недоступны или вы хотите полностью контролировать логику обхода строки, можно воспользоваться методом ручного разбора. Выясним причину популярности этого метода: он не зависит от внешних библиотек и позволяет гибко обрабатывать «слипшийся» текст.
Рассмотрим алгоритм, который ищет последовательность из 6 цифр, прерываемую любым нецифровым символом:
Функция ДайИндекс(стр)
Перем инд, рез, см;
рез = "";
Для инд = 1 По СтрДлина(стр) Цикл
см = Сред(стр, инд, 1);
// Проверяем, является ли символ цифрой
Если Найти("0123456789", см) > 0 Тогда
рез = рез + см;
Иначе
// Если накопили ровно 6 цифр и встретили разделитель - это индекс
Если СтрДлина(рез) = 6 Тогда
Возврат рез;
КонецЕсли;
рез = ""; // Сбрасываем накопленное, если цифр не 6
КонецЕсли;
КонецЦикла;
// Проверка для случая, когда индекс стоит в самом конце строки
Если СтрДлина(рез) = 6 Тогда
Возврат рез;
КонецЕсли;
Возврат "";
КонецФункции
Преимущество этого метода: Вы можете легко добавить дополнительные проверки. Например, если вы знаете, что индекс в вашем регионе начинается только на «6», вы можете добавить условие Лев(рез, 1) = "6".
В типовых конфигурациях (таких как Бухгалтерия предприятия 3.0, ERP или ЗУП) разработчики 1С уже предусмотрели мощные инструменты для работы с контактной информацией. Проанализируем возможности модуля УправлениеКонтактнойИнформацией.
Вместо того чтобы изобретать велосипед, мы можем вызвать функции, которые обращаются к адресному классификатору (ФИАС/ГАР). Рассмотрим примерный алгоритм:
УправлениеКонтактнойИнформацией.ДетализироватьАдрес.Индекс будет заполнено автоматически.Этот способ является наиболее надежным, так как он не просто ищет цифры, а проверяет существование такого адреса в реестре РФ.
Если задача стоит остро и данные в базе крайне замусорены (например, вместо индекса может быть написано «индекс отсутствует» или он указан с ошибкой), профессиональным решением будет использование внешних API. Разберем, как это работает:
Сервисы типа DaData принимают на вход «грязную» строку и возвращают структурированный JSON. Система сама найдет индекс, даже если его нет в исходной строке, основываясь на городе и улице. В 1С это реализуется через HTTPСоединение. Посмотрим на логику:
postal_code.Это гарантирует 100% точность для российских адресов, но требует наличия интернет-соединения и, зачастую, платной подписки при больших объемах данных.
При любом методе поиска цифр важно исключить ситуации, когда за индекс принимается что-то другое. Рассмотрим основные правила фильтрации:
+7, 8 или код города в скобках, игнорируйте этот фрагмент.Таким образом, выбор метода зависит от ваших требований к точности и версии платформы. Для простых задач вполне подойдет регулярное выражение, а для качественной очистки базы лучше использовать инструменты БСП или внешние сервисы стандартизации.