Как передать данные из модуля объекта в управляемую форму и почему ДополнительныеСвойства не работают?

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

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

Причина неработоспособности ДополнительныеСвойства в управляемых формах

Для начала разберем архитектурную проблему. В «обычном» приложении (толстый клиент) форма напрямую владела объектом типа ДокументОбъект. Этот объект существовал в памяти все время, пока была открыта форма. Соответственно, любые данные, записанные в ДополнительныеСвойства в модуле объекта, оставались доступными в форме.

В управляемом приложении ситуация в корне иная. Рассмотрим жизненный цикл создания документа на основании:

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

Проанализируем ситуацию: свойство ДополнительныеСвойства является частью типа ДокументОбъект, но оно не входит в состав реквизитов, которые платформа автоматически копирует в ДанныеФормыСтруктура. Поэтому, когда вы пытаетесь обратиться к Объект.ДополнительныеСвойства в форме, вы получаете ошибку «Поле объекта не обнаружено», так как у типа ДанныеФормыСтруктура просто нет такого свойства.

Даже если вы попытаетесь использовать функцию РеквизитФормыВЗначение("Объект"), это не поможет. Платформа создаст второй экземпляр объекта и заполнит его данными из формы. Но этот второй экземпляр ничего не знает о первом, который работал в ОбработкеЗаполнения, и его коллекция ДополнительныеСвойства будет пустой.

Решение №1: Использование параметров формы

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

Посмотрим на пример реализации проверки в процедуре ПриСозданииНаСервере. Мы можем проверить наличие документа-основания и выполнить необходимые проверки прямо здесь:


Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
    
    // Проверяем, что документ открывается для заполнения на основании
    Если Параметры.Свойство("Основание") И ЗначениеЗаполнено(Параметры.Основание) Тогда
        
        Основание = Параметры.Основание;
        
        // Выполняем проверку: не был ли уже создан документ по этому основанию
        Запрос = Новый Запрос;
        Запрос.Текст = 
            "ВЫБРАТЬ ПЕРВЫЕ 1
            |	Ссылка
            |ИЗ
            |	Документ.НашНовыйДокумент
            |ГДЕ
            |	ДокументОснование = &Основание
            |	И НЕ ПометкаУдаления";
        
        Запрос.УстановитьПараметр("Основание", Основание);
        РезультатЗапроса = Запрос.Выполнить();
        
        Если НЕ РезультатЗапроса.Пустой() Тогда
            ТекстСообщения = "Документ на основании " + Основание + " уже создан!";
            ОбщегоНазначенияКлиентСервер.СообщитьПользователю(ТекстСообщения);
            
            // Устанавливаем Отказ, чтобы форма не открылась
            Отказ = Истина;
        КонецЕсли;
        
    КонецЕсли;
    
КонецПроцедуры

Решение №2: Вызов исключения в модуле объекта

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

Рассмотрим пример кода в модуле объекта:


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

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

Решение №3: Скрытые реквизиты объекта

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

Алгоритм действий будет следующим:

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

Пример кода в форме:


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

Выясним, для чего на самом деле нужны ДополнительныеСвойства

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

Таким образом, для связи «Модуль объекта — Модуль управляемой формы» данный механизм технически не предназначен. Рекомендуется использовать либо параметры формы, либо механизм исключений, если речь идет о запрете операции.

Итоги и рекомендации

Подводя итог, можно сказать, что наиболее «чистым» решением с точки зрения архитектуры 1С является перенос проверок в процедуру ПриСозданииНаСервере модуля формы или использование ВызватьИсключение в модуле объекта. Если же вы используете современные конфигурации (ERP, УТ 11, КА 2), обратите внимание на механизмы БСП, такие как ПараметрыЗаполнения, которые позволяют гибко управлять процессом создания связанных документов без нарушения стандартов разработки.

← На главную