Как правильно отменить создание документа на основании, если проверка в ОбработкеЗаполнения не прошла?

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

При разработке в среде 1С:Предприятие программисты часто сталкиваются с ситуацией, когда создание нового документа на основании существующего должно быть разрешено только при выполнении определенных условий. Например, в конфигурации УПП 1.0 (Управление производственным предприятием) может потребоваться запретить создание Документа2, если в исходном Документе1 не заполнены ключевые реквизиты.

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

Почему Возврат в ОбработкеЗаполнения не работает так, как ожидается?

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

  1. В оперативной памяти сервера (или клиентского приложения в случае обычных форм) создается новый экземпляр объекта.
  2. Вызывается обработчик ОбработкаЗаполнения в модуле этого объекта. В него передается ссылка на документ-основание.
  3. Если в коде встречается Возврат, выполнение процедуры прекращается, но объект остается существовать в памяти.
  4. Платформа инициализирует форму этого объекта и вызывает события формы (ПередОткрытием, ПриОткрытии).
  5. Форма отображается пользователю.

Таким образом, процедура ОбработкаЗаполнения по своей сути не предназначена для принятия решения «создавать объект или нет». Ее задача — инициализировать реквизиты. Чтобы прервать процесс, нам нужно использовать другие механизмы.

Решение 1: Использование ДополнительныеСвойства и событий формы (для обычных форм)

В обычных формах (как в УПП 1.0) это самый распространенный и правильный способ. Мы передаем «флаг отказа» из модуля объекта в модуль формы через коллекцию ДополнительныеСвойства. Рассмотрим этот метод по шагам.

Шаг 1. Реализация логики в модуле объекта

В модуле Документа2 (приемника) пишем следующий код:


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

Шаг 2. Перехват в модуле формы

Теперь в модуле формы Документа2 нам нужно проверить наличие этого флага в событии ПередОткрытием. Если флаг установлен, мы отменяем открытие формы параметром Отказ.


Процедура ПередОткрытием(Отказ, СтандартнаяОбработка)
    
    // Проверяем наличие флага отказа, переданного из модуля объекта
    Если ДокументОбъект.ДополнительныеСвойства.Свойство("ОтказПриЗаполнении") Тогда
        Если ДокументОбъект.ДополнительныеСвойства.ОтказПриЗаполнении = Истина Тогда
            // Отменяем открытие формы
            Отказ = Истина;
        КонецЕсли;
    КонецЕсли;
    
КонецПроцедуры

Решение 2: Использование исключений (Жесткий способ)

Если вам нужно гарантированно прервать создание документа не только при интерактивном вводе, но и при программном вызове, можно использовать механизм исключений. Вызов ВызватьИсключение прерывает выполнение кода немедленно.


Процедура ОбработкаЗаполнения(ДанныеЗаполнения, ТекстЗаполнения, СтандартнаяОбработка)
    
    Если ТипЗнч(ДанныеЗаполнения) = Тип("ДокументСсылка.Документ1") Тогда
        Если НЕ ЗначениеЗаполнено(ДанныеЗаполнения.ВажноеПоле) Тогда
            ВызватьИсключение "Ошибка: документ не может быть создан без заполненного поля в основании!";
        КонецЕсли;
    КонецЕсли;
    
КонецПроцедуры

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

Решение 3: Перенос проверки в Документ-основание

Рассмотрим ситуацию с точки зрения удобства пользователя. Зачем вообще нажимать кнопку «Создать на основании», если мы заранее знаем, что документ создать нельзя? Мы можем переопределить команду создания прямо в форме Документа1.

  1. Найдите в форме Документа1 кнопку (или пункт меню), отвечающую за ввод на основании.
  2. Если она стандартная, отключите ее автоматическую генерацию и создайте свою кнопку с аналогичным именем.
  3. В обработчике нажатия этой кнопки выполните проверку.

Процедура КоманднаяПанельДействияСоздатьНаОсновании(Кнопка)
    
    // Сначала проверяем условия прямо здесь
    Если НЕ ЗначениеЗаполнено(ВажноеПоле) Тогда
        Предупреждение("Заполните поле 'Важное поле' перед созданием зависимых документов!");
        Возврат;
    КонецЕсли;
    
    // Если всё хорошо, вызываем штатный механизм создания
    // Например, через ОткрытьФорму или выполнение стандартной команды
    // ...
КонецПроцедуры

Особенности для Управляемых Форм (8.3)

Хотя в вопросе упоминается УПП на обычных формах, полезно знать, как эта задача решается в современном интерфейсе. В управляемых формах событие ПриСозданииНаСервере имеет доступ к параметру Параметры.ЗначениеЗаполнения.

Проанализируем пример кода для управляемой формы:


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

Резюме

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

Используя эти методы, вы обеспечите стабильную работу системы и избавите пользователей от появления пустых или некорректных документов в базе данных.

← На главную