В процессе разработки на платформе 1С:Предприятие 8 часто возникает ситуация, когда стандартного поведения системы при проверке заполнения реквизитов становится недостаточно. Например, когда поле в конфигураторе помечено как обязательное («Выдавать ошибку»), но при определенных условиях нам нужно позволить пользователю оставить его пустым. Разберем подробно, как работает механизм ОбработкаПроверкиЗаполнения, и выясним, почему простая установка Отказ = Ложь не приводит к желаемому результату.
Для начала проанализируем, как платформа инициирует проверку. Когда пользователь нажимает кнопку «Записать» или «Провести», либо когда в коде вызывается метод ПроверитьЗаполнение(), запускается следующий алгоритм:
ПроверяемыеРеквизиты.ОбработкаПроверкиЗаполнения (сначала в модуле формы, затем в модуле объекта).Отказ (булево) и ПроверяемыеРеквизиты (массив строк с именами полей).ПроверяемыеРеквизиты. Если в массиве осталось имя поля, а само поле не заполнено, система выводит сообщение об ошибке и устанавливает Отказ = Истина автоматически.Из этого алгоритма становится понятно, почему попытка просто написать Отказ = Ложь в конце процедуры не помогает. Если реквизит остался в массиве ПроверяемыеРеквизиты и он пуст, платформа сама изменит значение Отказ обратно в Истина сразу после выхода из процедуры.
Чтобы система «забыла» о необходимости проверять конкретное поле, которое в конфигураторе настроено как обязательное, мы должны физически удалить его имя из массива ПроверяемыеРеквизиты. Рассмотрим, как это сделать на примере реквизита Склад.
Выполним следующие шаги в коде модуля объекта:
Процедура ОбработкаПроверкиЗаполнения(Отказ, ПроверяемыеРеквизиты)
// Определяем индекс нужного нам реквизита в массиве
ПорядковыйНомер = ПроверяемыеРеквизиты.Найти("Склад");
// Если реквизит найден в списке проверяемых, удаляем его
Если ПорядковыйНомер <> Неопределено Тогда
ПроверяемыеРеквизиты.Удалить(ПорядковыйНомер);
КонецЕсли;
КонецПроцедуры
Этот подход позволяет нам гибко управлять логикой. Например, мы можем удалять реквизит из проверки только для определенных категорий пользователей или в зависимости от состояния других полей объекта. Рассмотрим ситуацию, когда поле Контрагент обязательно только для юридических лиц:
Процедура ОбработкаПроверкиЗаполнения(Отказ, ПроверяемыеРеквизиты)
Если ЮридическоеЛицо = Ложь Тогда
// Для физических лиц контрагент может быть не заполнен
Индекс = ПроверяемыеРеквизиты.Найти("Контрагент");
Если Индекс <> Неопределено Тогда
ПроверяемыеРеквизиты.Удалить(Индекс);
КонецЕсли;
КонецЕсли;
КонецПроцедуры
Часто разработчики, имеющие опыт работы в версии 7.7, допускают ошибку при проверке того, является ли элемент справочника группой. В седьмой версии ЭтоГруппа() была функцией, поэтому требовала скобок. В 1С 8.х — это булево свойство (реквизит) объекта.
Если вы напишете Если ЭтоГруппа() Тогда, система выдаст ошибку «Процедура или функция с указанным именем не определена». Правильный код для исключения проверок у групп справочника выглядит так:
Процедура ОбработкаПроверкиЗаполнения(Отказ, ПроверяемыеРеквизиты)
// В 1С 8.3 ЭтоГруппа — это свойство, скобки не нужны
Если ЭтоГруппа Тогда
// Для групп обычно никакие проверки заполнения не нужны
ПроверяемыеРеквизиты.Очистить();
Возврат;
КонецЕсли;
// Далее идет логика для элементов
КонецПроцедуры
Если ваша задача — не просто отключить стандартную проверку, а добавить свою сложную логику, вам потребуется параметр Отказ и объект СообщениеПользователю. Важно помнить: если вы просто напишете Сообщить("Ошибка!") и Отказ = Истина, пользователь увидит текст, но не поймет, какое поле на форме вызвало проблему.
Проанализируем правильный способ вывода ошибок, чтобы поле на форме «подсветилось» красным:
Процедура ОбработкаПроверкиЗаполнения(Отказ, ПроверяемыеРеквизиты)
// Допустим, нам нужно проверить корректность даты
Если Дата < '20230101' Тогда
ТекстОшибки = "Дата документа не может быть ранее 2023 года!";
// Создаем объект сообщения
Сообщение = Новый СообщениеПользователю;
Сообщение.Текст = ТекстОшибки;
Сообщение.Поле = "Дата"; // Имя реквизита, как оно названо в объекте
Сообщение.УстановитьДанные(ЭтотОбъект); // Привязываем к текущему объекту
Сообщение.Сообщить();
Отказ = Истина;
КонецЕсли;
КонецПроцедуры
Важный нюанс: если вы добавляете проверку вручную и устанавливаете Отказ = Истина, платформа всё равно проверит остальные реквизиты из массива ПроверяемыеРеквизиты. Это удобно, так как пользователь получит сразу весь список замечаний, а не будет исправлять их по одному.
Выбор места реализации проверки зависит от бизнес-задачи. Выясним основные отличия:
Общая рекомендация: фундаментальные проверки, касающиеся состава данных, всегда выносите в модуль объекта. В форме оставляйте только специфичные интерфейсные проверки.
Иногда программисты удивляются, почему их код в ОбработкаПроверкиЗаполнения не выполняется. Посмотрим на основные причины:
ОбменДанными.Загрузка установлено в Истина, платформа отключает большинство проверок, чтобы ускорить процесс и избежать конфликтов.Записать(), проверка запускается только если не указан режим РежимЗаписиДокумента.Запись (для документов) или если явно не переданы параметры отмены проверки.Подводя итог, можно сказать, что механизм ОбработкаПроверкиЗаполнения — это мощный инструмент управления качеством данных. Главное правило: если нужно «отменить» обязательность поля, заданную в конфигураторе — удаляйте его из массива ПроверяемыеРеквизиты. Если нужно добавить условие — проверяйте его кодом и управляйте параметром Отказ совместно с выводом качественных сообщений пользователю.