В процессе разработки конфигураций на платформе «1С:Предприятие» перед нами часто встает задача жесткого контроля вводимых данных. Одним из классических примеров является ограничение длины наименования элемента справочника. На первый взгляд, задача выглядит тривиальной: достаточно написать несколько строк кода в модуле объекта. Однако на практике разработчики часто сталкиваются с ситуацией, когда проверка обходится, и в базу данных записываются некорректные элементы.
В этой статье мы подробно разберем, почему стандартная проверка длины строки может не работать, как на это влияют маски ввода, как правильно организовать валидацию данных, а также рассмотрим важные аспекты серверной отладки и правила написания обработчиков событий в модуле объекта.
Рассмотрим стандартную ситуацию. Разработчик хочет заставить пользователей вводить наименование строго определенной длины (например, ровно 17 символов). Для этого в модуле объекта справочника создается следующий обработчик события:
Процедура ПередЗаписью(Отказ)
Если СтрДлина(ЭтотОбъект.Наименование) <> 17 Тогда
Отказ = Истина;
КонецЕсли;
КонецПроцедуры
Казалось бы, логика безупречна. Если длина наименования не равна 17, транзакция записи должна отменяться. Но при тестировании выясняется, что система спокойно записывает элементы, в которых визуально введено гораздо меньше символов.
Проанализируем ситуацию подробнее. Главный виновник такого поведения — маска ввода, настроенная на поле ввода наименования в форме. Маска ввода (например, для ввода артикулов, серийных номеров или кодов) автоматически форматирует текст. Если маска предусматривает фиксированную длину и разделение символов точками, дефисами или пробелами, то при неполном заполнении поля платформа 1С автоматически дополняет незаполненные позиции пробелами.
В результате в базу данных отправляется строка, которая визуально кажется короткой, но на самом деле содержит концевые пробелы. Метод СтрДлина() честно подсчитывает эти пробелы, возвращает значение 17, и проверка успешно проходится, допуская запись некорректных данных.
Самый простой и быстрый способ решить проблему с концевыми пробелами — использовать встроенную функцию СокрЛП() (Сократить Левые и Правые пробелы). Данная функция удаляет все незначащие пробелы в начале и в конце текстовой строки.
Модернизируем наш код в модуле объекта справочника:
Процедура ПередЗаписью(Отказ)
Если СтрДлина(СокрЛП(ЭтотОбъект.Наименование)) <> 17 Тогда
Отказ = Истина;
КонецЕсли;
КонецПроцедуры
Теперь перед проверкой длины все скрытые концевые пробелы, которые подставила маска ввода, будут безжалостно удалены, и платформа корректно определит реальную длину значимой части строки.
Хотя функция СокрЛП() отлично справляется с пробелами по краям строки, она имеет серьезный недостаток — она совершенно не трогает пробелы внутри текста.
Представим ситуацию: пользователь вводил данные по маске типа 99.99.99.99, но пропустил символы в середине строки. В результате получилось значение вида "12. .56.78". Функция СокрЛП() вернет эту же строку без изменений, так как пробелы находятся внутри. Метод СтрДлина() опять вернет полную длину, хотя фактически данные введены некорректно.
Чтобы гарантировать 100% надежность проверки, нам необходимо очистить строку от всех нерелевантных символов (пробелов, точек, дефисов и других разделителей маски) перед анализом ее длины. Разберем по шагам, как это реализовать:
Процедура ПередЗаписью(Отказ)
// Очищаем наименование от пробелов и точек-разделителей
ЧистоеНаименование = СтрЗаменить(ЭтотОбъект.Наименование, " ", "");
ЧистоеНаименование = СтрЗаменить(ЧистоеНаименование, ".", "");
// Проверяем длину очищенной строки (например, ожидаем ровно 8 цифр без учета точек)
Если СтрДлина(ЧистоеНаименование) <> 8 Тогда
Отказ = Истина;
Общего НазначенияКлиентСервер.СообщитьПользователю("Наименование заполнено некорректно!");
КонецЕсли;
КонецПроцедуры
Такой подход полностью исключает возможность сохранения полупустых значений, замаскированных под корректный ввод.
Часто разработчики сталкиваются с аппаратными ограничениями среды разработки. Например, когда код выполняется на сервере приложений, где из соображений производительности или безопасности администраторами отключена серверная отладка. Как в таких условиях понять, что именно содержится в переменной?
Рассмотрим три эффективных метода «слепой» отладки:
ЗаписьЖурналаРегистрации("ОтладкаПроверки",
УровеньЖурналаРегистрации.Информация,
,
,
"Значение: '" + ЭтотОбъект.Наименование + "'; Длина: " + СтрДлина(ЭтотОбъект.Наименование));
ВызватьИсключение "Отладка! Значение: '" + ЭтотОбъект.Наименование + "', Длина: " + СтрДлина(ЭтотОбъект.Наименование);
Разрабатывая проверки в модуле объекта, начинающие программисты часто забывают о существовании механизмов синхронизации и обмена данными (например, РИБ или интеграции через EnterpriseData).
Если в базу данных будут загружаться элементы из другой системы, жесткое прерывание транзакции через Отказ = Истина заблокирует весь процесс обмена данными. При загрузке данных интерактивные правила валидации применяться не должны!
Давайте посмотрим на единственно верный шаблон написания процедуры ПередЗаписью в модуле объекта:
Процедура ПередЗаписью(Отказ)
// КРИТИЧЕСКИ ВАЖНО: пропускаем проверку при загрузке данных
Если ОбменДанными.Загрузка Тогда
Возврат;
КонецЕсли;
// Наша логика проверки
ОчищенныйТекст = СтрЗаменить(СокрЛП(ЭтотОбъект.Наименование), " ", "");
Если СтрДлина(ОчищенныйТекст) <> 17 Тогда
Отказ = Истина;
КонецЕсли;
КонецПроцедуры
Использование свойства ОбменДанными.Загрузка гарантирует, что ваши проверки не нарушат стабильность обмена данными и автоматического обновления конфигурации.
Иногда разработчики совершают досадные опечатки при ручном написании сигнатур процедур (например, пишут ПередЗаписью(Отказ, Источник) или путают буквы в названии). Чтобы избежать подобных ошибок, всегда используйте встроенные инструменты Конфигуратора.
Разберем по шагам, как сгенерировать шаблон процедуры:
ПередЗаписью или ПриЗаписи).Использование шаблонов конфигуратора — это признак хорошего тона в разработке и надежная защита от трудночитаемых синтаксических ошибок.