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