Как передать параметр из обработки заполнения в управляемую форму документа

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

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

В этой статье мы подробно разберем, как передать данные «сквозь» платформенные механизмы, проанализируем последовательность событий и выберем наиболее архитектурно правильные решения для управляемого приложения.

Анализ последовательности событий

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

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

Поскольку экземпляр объекта в пункте 2 и объект в форме в пункте 4 — это разные программные сущности, любые экспортные переменные модуля объекта будут потеряны. Нам необходимо «привязать» данные к самому объекту или использовать общие хранилища.

Способ 1. Использование коллекции ДополнительныеСвойства

Рассмотрим самый профессиональный способ — использование системной коллекции ДополнительныеСвойства. Этот механизм специально предназначен для передачи произвольной информации внутри объекта в рамках одного серверного вызова.

Разберем реализацию по шагам. Сначала в модуле объекта (или в расширении модуля объекта с типом вызова &После или &Вместо) зафиксируем нужный нам параметр:


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

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


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

Важный момент: Метод РеквизитФормыВЗначение является ресурсоемким, так как создает полную копию объекта в памяти. Используйте его осознанно только при необходимости передачи сложных структур.

Способ 2. Использование технического реквизита (Способ «Бинго»)

Рассмотрим более простой, хотя и менее эстетичный метод, упомянутый в обсуждении. Если создание документа происходит в один этап, мы можем использовать любой строковый реквизит документа (например, Комментарий) или создать специальный скрытый реквизит ТехническийПараметр.

Логика работы заключается в следующем:

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

Посмотрим на пример кода в модуле формы:


&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
    
    Если Найти(Объект.Комментарий, "ЗАПУСТИТЬ_ЗАПОЛНЕНИЕ_ТЧ") > 0 Тогда
        // Выполняем процедуру, которая определена в форме
        ЗаполнитьТабличнуюЧастьПоЛогикеФормы();
        
        // Очищаем «грязный» реквизит
        Объект.Комментарий = "";
    КонецЕсли;
    
КонецПроцедуры

Этот способ хорош тем, что не требует вызова РеквизитФормыВЗначение, но он не подходит, если Комментарий уже используется пользователем или если данные имеют сложную структуру (например, Таблица Значений).

Способ 3. Расширение формы и перехват процедур

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

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

Это позволит вам:

Способ 4. Использование временного хранилища

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

  1. В ОбработкаЗаполнения помещаем данные в хранилище.
  2. Адрес хранилища передаем через ДополнительныеСвойства (как в способе 1).
  3. В форме извлекаем данные по адресу.

// В модуле объекта
Адрес = ПоместитьВоВременноеХранилище(ТаблицаДанных, Новый УникальныйИдентификатор);
ЭтотОбъект.ДополнительныеСвойства.Вставить("АдресДанных", Адрес);

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

Резюме

Выбор метода зависит от сложности задачи:

← На главную