В практике разработки на платформе 1С часто возникает ситуация, когда логика заполнения документа сосредоточена в модуле объекта (в процедуре ОбработкаЗаполнения), но после создания объекта требуется выполнить определенные действия непосредственно в форме — например, запустить специфическую визуальную обработку табличной части или изменить состояние элементов управления. Трудность заключается в том, что при стандартном открытии формы (через команду "Создать") у разработчика нет прямого доступа к параметрам открытия формы из модуля объекта.
В этой статье мы подробно разберем, как передать данные «сквозь» платформенные механизмы, проанализируем последовательность событий и выберем наиболее архитектурно правильные решения для управляемого приложения.
Прежде чем переходить к коду, давайте выясним причину, по которой обычные экспортные переменные не работают. Когда пользователь нажимает кнопку «Создать», платформа выполняет следующие действия в строгой последовательности:
ОбработкаЗаполнения в модуле объекта (или в расширении модуля объекта).ПриСозданииНаСервере.Поскольку экземпляр объекта в пункте 2 и объект в форме в пункте 4 — это разные программные сущности, любые экспортные переменные модуля объекта будут потеряны. Нам необходимо «привязать» данные к самому объекту или использовать общие хранилища.
Рассмотрим самый профессиональный способ — использование системной коллекции ДополнительныеСвойства. Этот механизм специально предназначен для передачи произвольной информации внутри объекта в рамках одного серверного вызова.
Разберем реализацию по шагам. Сначала в модуле объекта (или в расширении модуля объекта с типом вызова &После или &Вместо) зафиксируем нужный нам параметр:
Процедура ОбработкаЗаполнения(ДанныеЗаполнения, ТекстЗаполнения, СтандартнаяОбработка)
// Устанавливаем флаг, что объект был заполнен программно
ЭтотОбъект.ДополнительныеСвойства.Вставить("ЗапуститьОбработкуФормы", Истина);
ЭтотОбъект.ДополнительныеСвойства.Вставить("СпециальноеЗначение", "Параметр из модуля");
КонецПроцедуры
Теперь в модуле формы нам нужно «поймать» эти свойства. Однако есть нюанс: в процедуре ПриСозданииНаСервере основной реквизит Объект имеет тип ДанныеФормыСтруктура, у которого нет коллекции ДополнительныеСвойства. Чтобы получить к ним доступ, нам нужно временно преобразовать данные формы обратно в объект.
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
// Преобразуем данные формы в объект для чтения свойств
ТекущийОбъект = РеквизитФормыВЗначение("Объект");
Если ТекущийОбъект.ДополнительныеСвойства.Свойство("ЗапуститьОбработкуФормы") Тогда
// Передаем флаг в переменную формы, чтобы использовать ее позже
ЭтаФорма.НужноВыполнитьЗаполнениеНаФорме = Истина;
КонецЕсли;
КонецПроцедуры
Важный момент: Метод РеквизитФормыВЗначение является ресурсоемким, так как создает полную копию объекта в памяти. Используйте его осознанно только при необходимости передачи сложных структур.
Рассмотрим более простой, хотя и менее эстетичный метод, упомянутый в обсуждении. Если создание документа происходит в один этап, мы можем использовать любой строковый реквизит документа (например, Комментарий) или создать специальный скрытый реквизит ТехническийПараметр.
Логика работы заключается в следующем:
ОбработкаЗаполнения мы записываем данные в реквизит Объект.Комментарий.ПриСозданииНаСервере мы читаем этот реквизит.Посмотрим на пример кода в модуле формы:
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
Если Найти(Объект.Комментарий, "ЗАПУСТИТЬ_ЗАПОЛНЕНИЕ_ТЧ") > 0 Тогда
// Выполняем процедуру, которая определена в форме
ЗаполнитьТабличнуюЧастьПоЛогикеФормы();
// Очищаем «грязный» реквизит
Объект.Комментарий = "";
КонецЕсли;
КонецПроцедуры
Этот способ хорош тем, что не требует вызова РеквизитФормыВЗначение, но он не подходит, если Комментарий уже используется пользователем или если данные имеют сложную структуру (например, Таблица Значений).
Проанализируем ситуацию, когда автор хочет «запустить код, который весь в форме». Если вы используете расширение, лучшим решением будет не пытаться передать флаг, а изменить саму логику вызова процедур формы.
Если код заполнения табличной части находится в процедуре формы, например ЗаполнитьДанные(), вы можете добавить эту форму в расширение и переопределить ее поведение. Нажмите правой кнопкой мыши на процедуру -> «Добавить в расширение» -> «Вместо».
Это позволит вам:
ПродолжитьВызов().Если объем данных велик (например, массив структур или большая таблица), лучше всего использовать ВременноеХранилище. Выясним, как связать адрес хранилища с новой формой:
ОбработкаЗаполнения помещаем данные в хранилище.ДополнительныеСвойства (как в способе 1).
// В модуле объекта
Адрес = ПоместитьВоВременноеХранилище(ТаблицаДанных, Новый УникальныйИдентификатор);
ЭтотОбъект.ДополнительныеСвойства.Вставить("АдресДанных", Адрес);
// В модуле формы
Адрес = "";
Если ТекущийОбъект.ДополнительныеСвойства.Свойство("АдресДанных", Адрес) Тогда
НужныеДанные = ПолучитьИзВременногоХранилища(Адрес);
КонецЕсли;
Выбор метода зависит от сложности задачи:
Комментарий.РеквизитФормыВЗначение.