Как программно управлять проверкой заполнения и почему параметр Отказ не всегда отменяет ошибки в 1С

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

В процессе разработки на платформе 1С:Предприятие 8 часто возникает ситуация, когда стандартного поведения системы при проверке заполнения реквизитов становится недостаточно. Например, когда поле в конфигураторе помечено как обязательное («Выдавать ошибку»), но при определенных условиях нам нужно позволить пользователю оставить его пустым. Разберем подробно, как работает механизм ОбработкаПроверкиЗаполнения, и выясним, почему простая установка Отказ = Ложь не приводит к желаемому результату.

Механика работы события ОбработкаПроверкиЗаполнения

Для начала проанализируем, как платформа инициирует проверку. Когда пользователь нажимает кнопку «Записать» или «Провести», либо когда в коде вызывается метод ПроверитьЗаполнение(), запускается следующий алгоритм:

  1. Система анализирует метаданные объекта. Все реквизиты, у которых свойство Проверка заполнения установлено в значение Выдавать ошибку, автоматически помещаются в специальный массив ПроверяемыеРеквизиты.
  2. Вызывается обработчик события ОбработкаПроверкиЗаполнения (сначала в модуле формы, затем в модуле объекта).
  3. В этот обработчик передаются два ключевых параметра: Отказ (булево) и ПроверяемыеРеквизиты (массив строк с именами полей).
  4. После выполнения кода в обработчике система приступает к обходу массива ПроверяемыеРеквизиты. Если в массиве осталось имя поля, а само поле не заполнено, система выводит сообщение об ошибке и устанавливает Отказ = Истина автоматически.

Из этого алгоритма становится понятно, почему попытка просто написать Отказ = Ложь в конце процедуры не помогает. Если реквизит остался в массиве ПроверяемыеРеквизиты и он пуст, платформа сама изменит значение Отказ обратно в Истина сразу после выхода из процедуры.

Как исключить реквизит из проверки программно

Чтобы система «забыла» о необходимости проверять конкретное поле, которое в конфигураторе настроено как обязательное, мы должны физически удалить его имя из массива ПроверяемыеРеквизиты. Рассмотрим, как это сделать на примере реквизита Склад.

Выполним следующие шаги в коде модуля объекта:


Процедура ОбработкаПроверкиЗаполнения(Отказ, ПроверяемыеРеквизиты)
    
    // Определяем индекс нужного нам реквизита в массиве
    ПорядковыйНомер = ПроверяемыеРеквизиты.Найти("Склад");
    
    // Если реквизит найден в списке проверяемых, удаляем его
    Если ПорядковыйНомер <> Неопределено Тогда
        ПроверяемыеРеквизиты.Удалить(ПорядковыйНомер);
    КонецЕсли;
    
КонецПроцедуры

Этот подход позволяет нам гибко управлять логикой. Например, мы можем удалять реквизит из проверки только для определенных категорий пользователей или в зависимости от состояния других полей объекта. Рассмотрим ситуацию, когда поле Контрагент обязательно только для юридических лиц:


Процедура ОбработкаПроверкиЗаполнения(Отказ, ПроверяемыеРеквизиты)
    
    Если ЮридическоеЛицо = Ложь Тогда
        // Для физических лиц контрагент может быть не заполнен
        Индекс = ПроверяемыеРеквизиты.Найти("Контрагент");
        Если Индекс <> Неопределено Тогда
            ПроверяемыеРеквизиты.Удалить(Индекс);
        КонецЕсли;
    КонецЕсли;
    
КонецПроцедуры

Проблема использования функций из 1С 7.7: случай с ЭтоГруппа

Часто разработчики, имеющие опыт работы в версии 7.7, допускают ошибку при проверке того, является ли элемент справочника группой. В седьмой версии ЭтоГруппа() была функцией, поэтому требовала скобок. В 1С 8.х — это булево свойство (реквизит) объекта.

Если вы напишете Если ЭтоГруппа() Тогда, система выдаст ошибку «Процедура или функция с указанным именем не определена». Правильный код для исключения проверок у групп справочника выглядит так:


Процедура ОбработкаПроверкиЗаполнения(Отказ, ПроверяемыеРеквизиты)
    
    // В 1С 8.3 ЭтоГруппа — это свойство, скобки не нужны
    Если ЭтоГруппа Тогда
        // Для групп обычно никакие проверки заполнения не нужны
        ПроверяемыеРеквизиты.Очистить();
        Возврат;
    КонецЕсли;
    
    // Далее идет логика для элементов
КонецПроцедуры

Собственные проверки и использование СообщениеПользователю

Если ваша задача — не просто отключить стандартную проверку, а добавить свою сложную логику, вам потребуется параметр Отказ и объект СообщениеПользователю. Важно помнить: если вы просто напишете Сообщить("Ошибка!") и Отказ = Истина, пользователь увидит текст, но не поймет, какое поле на форме вызвало проблему.

Проанализируем правильный способ вывода ошибок, чтобы поле на форме «подсветилось» красным:


Процедура ОбработкаПроверкиЗаполнения(Отказ, ПроверяемыеРеквизиты)
    
    // Допустим, нам нужно проверить корректность даты
    Если Дата < '20230101' Тогда
        
        ТекстОшибки = "Дата документа не может быть ранее 2023 года!";
        
        // Создаем объект сообщения
        Сообщение = Новый СообщениеПользователю;
        Сообщение.Текст = ТекстОшибки;
        Сообщение.Поле  = "Дата"; // Имя реквизита, как оно названо в объекте
        Сообщение.УстановитьДанные(ЭтотОбъект); // Привязываем к текущему объекту
        Сообщение.Сообщить();
        
        Отказ = Истина;
        
    КонецЕсли;
    
КонецПроцедуры

Важный нюанс: если вы добавляете проверку вручную и устанавливаете Отказ = Истина, платформа всё равно проверит остальные реквизиты из массива ПроверяемыеРеквизиты. Это удобно, так как пользователь получит сразу весь список замечаний, а не будет исправлять их по одному.

Где лучше писать код: в модуле формы или в модуле объекта?

Выбор места реализации проверки зависит от бизнес-задачи. Выясним основные отличия:

  1. Модуль объекта: Код здесь сработает всегда, независимо от того, записывается объект из формы, программно из обработки или через веб-сервис. Это гарантирует целостность данных в базе. Однако в модуле объекта доступны только данные самого объекта.
  2. Модуль формы: Код сработает только при записи через конкретную форму. Здесь можно проверять значения, которые не хранятся в базе, а существуют только «на экране» (например, вспомогательные флажки или переменные формы).

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

Когда проверка заполнения не срабатывает вовсе

Иногда программисты удивляются, почему их код в ОбработкаПроверкиЗаполнения не выполняется. Посмотрим на основные причины:

Подводя итог, можно сказать, что механизм ОбработкаПроверкиЗаполнения — это мощный инструмент управления качеством данных. Главное правило: если нужно «отменить» обязательность поля, заданную в конфигураторе — удаляйте его из массива ПроверяемыеРеквизиты. Если нужно добавить условие — проверяйте его кодом и управляйте параметром Отказ совместно с выводом качественных сообщений пользователю.

← На главную