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