Как программно настроить проверку заполнения реквизитов только для определенной формы в 1С?

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

В процессе кастомизации типовых конфигураций 1С (например, 1С:ERP, 1С:Управление торговлей или 1С:Комплексная автоматизация) разработчики часто сталкиваются с необходимостью создания альтернативных форм для стандартных документов. Представим ситуацию: для документа "Заявка на расходование денежных средств" создана новая, измененная форма. На эту форму выведены дополнительные реквизиты, которые обязательны к заполнению.

Однако если мы просто настроим стандартную проверку заполнения этих реквизитов в конфигураторе, система начнет требовать их заполнения везде, включая типовую форму документа. Это приведет к ошибкам у пользователей, работающих в стандартном интерфейсе. Как правильно разграничить логику проверки для разных форм? Разберем подробно несколько практических способов реализации этой задачи, проанализируем их плюсы и минусы, а также изучим подводные камни платформы 1С.

Вариант 1. Использование обработчика управляемой формы ОбработкаПроверкиЗаполненияНаСервере (Рекомендуемый)

Это наиболее элегантное и архитектурно правильное решение в управляемом приложении. Оно позволяет изолировать логику проверки исключительно внутри вашей новой формы, вообще не затрагивая модуль объекта и не создавая лишних расширений для серверной логики.

Для реализации этого метода выполним следующие шаги:

  1. Откроем свойства добавленных вами реквизитов в конфигураторе и установим свойство Проверка заполнения в значение Не проверять. Это критически важно, чтобы стандартная проверка платформы не ругалась на них при записи из других форм или при программном создании документа.
  2. Перейдем в модуль нашей новой измененной управляемой формы.
  3. Создадим на сервере предопределенный обработчик ОбработкаПроверкиЗаполненияНаСервере.

Рассмотрим пример кода, который необходимо поместить в модуль формы:


&НаСервере
Процедура ОбработкаПроверкиЗаполненияНаСервере(Отказ, ПроверяемыеРеквизиты)
    
    // Добавляем реквизиты нашего объекта, которые обязательны ТОЛЬКО на этой форме
    ПроверяемыеРеквизиты.Добавить("Объект.НовыйРеквизитДляПроверки");
    ПроверяемыеРеквизиты.Добавить("Объект.ЕщеОдинВажныйРеквизит");
    
КонецПроцедуры

Выясним, почему данный метод считается идеальным с точки зрения архитектуры 1С:

Вариант 2. Проверка заполнения реквизитов в модуле объекта через расширение

Иногда требуется реализовать проверку в модуле объекта, например, когда состав проверяемых реквизитов зависит от сложных условий или определенных бизнес-правил самого объекта, а не только от интерфейса. Для этого используется предопределенная процедура модуля объекта ОбработкаПроверкиЗаполнения.

Если мы работаем в типовой конфигурации, лучшим решением будет использование расширения конфигурации. Мы можем перехватить обработку проверки заполнения и динамически управлять составом массива проверяемых реквизитов.

Посмотрим на пример реализации такого кода в модуле объекта через расширение:


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

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

Опасная ловушка: Порядок событий и передача параметров через ДополнительныеСвойства

На форумах часто советуют передавать признак открытой формы в модуль объекта при записи через структуру ДополнительныеСвойства объекта (например, заполняя флаг "ИспользованаНоваяФорма" на клиенте перед записью). Будьте предельно осторожны: здесь кроется классическая ловушка, связанная с жесткой последовательностью выполнения платформенных событий при записи документа.

Давайте проанализируем цепочку вызовов при интерактивном нажатии кнопки "Записать" на форме:

  1. Событие формы на клиенте: ПередЗаписью
  2. Событие формы на сервере: ОбработкаПроверкиЗаполненияНаСервере
  3. Событие объекта на сервере: ОбработкаПроверкиЗаполнения
  4. Событие формы на сервере: ПередЗаписьюНаСервере (именно здесь разработчики чаще всего пытаются инициализировать ДополнительныеСвойства объекта!)
  5. Событие объекта на сервере: ПередЗаписью
  6. Событие объекта на сервере: ПриЗаписи (старт транзакции базы данных)

Вывод очевиден: проверка заполнения на уровне модуля объекта (шаг 3) выполняется раньше, чем срабатывает обработчик формы ПередЗаписьюНаСервере (шаг 4). Если вы попытаетесь передать флаг активной формы в ДополнительныеСвойства внутри события ПередЗаписьюНаСервере, то в момент проверки в модуле объекта эта структура гарантированно будет пустой, и проверка отработает некорректно!

Если вам все же критически необходимо передать параметры из формы в модуль объекта для проверки заполнения, выполнять это нужно строго в клиентском обработчике ПередЗаписью на форме перед вызовом стандартного механизма записи, либо использовать первый вариант с проверкой непосредственно в форме.

Вариант 3. Проверка "по старинке" в событии ПередЗаписью (Почему это антипаттерн?)

В старых конфигурациях на обычных формах часто использовался подход с ручной проверкой через функцию ЗначениеЗаполнено() непосредственно в обработчике ПередЗаписью модуля объекта или формы. Выглядит это примерно так:


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

Давайте разберем, почему данный подход крайне не рекомендуется использовать в современной разработке на платформе 1С:Предприятие 8.3:

Интерактивная запись против программной записи

При выборе места для размещения кода проверки заполнения всегда учитывайте важнейший аспект: как именно данный документ будет создаваться и записываться в систему?

Если запись происходит интерактивно (пользователь нажимает кнопку в интерфейсе), система последовательно выполняет события и формы, и объекта. В этом случае отлично работают как проверки в модуле формы, так и проверки в модуле объекта.

Если же запись происходит программно (документ загружается через API, веб-сервисы, файлы Excel, или создается регламентным заданием в фоне), то события формы не вызываются вообще. Будет задействован исключительно модуль объекта.

Если вы жестко пропишете обязательность заполнения новых полей в модуле объекта без дополнительных условий, то при любом программном обмене данными система начнет сыпать ошибками о незаполненных реквизитах, блокируя загрузку. Использование гибкого разделения проверок с помощью первого варианта (на уровне измененной формы) полностью защищает вас от этой проблемы: пользователи в новой форме обязаны заполнять поля, а внешние интеграции и стандартные формы продолжают стабильно функционировать без сбоев.

← На главную