Как передать владельца при программном открытии формы нового объекта в 1С

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

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

Разбор типичной ошибки: почему ЗначениеВРеквизитФормы не подходит

В исходном вопросе автор пытался использовать метод ЗначениеВРеквизитФормы(Параметры.Основание, "Владелец"). Разберем, почему это привело к ошибке «Недопустимое значение параметра (параметр номер '2')». Проанализируем ситуацию:

  1. Назначение метода: Метод ЗначениеВРеквизитФормы предназначен для преобразования прикладного объекта (например, типа СправочникОбъект) в данные формы (тип ДанныеФормыСтруктура). Его обычно используют, когда нужно программно изменить весь объект на сервере и «загрузить» его обратно в реквизит формы «Объект».
  2. Иерархия реквизитов: В управляемой форме справочника поле «Владелец» не является самостоятельным реквизитом формы первого уровня. Оно является свойством (реквизитом) основного реквизита формы Объект. То есть путь к данным выглядит как Объект.Владелец.
  3. Тип данных: Поле «Владелец» ожидает Ссылку (СправочникСсылка.Стеллаж), в то время как метод ЗначениеВРеквизитФормы ожидает во втором параметре имя реквизита, который связан с типом данных всего передаваемого объекта.

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

Способ 1. Использование стандартного параметра «ЗначениеЗаполнения» (Рекомендуемый)

Это наиболее «православный» и правильный с точки зрения платформы 1С метод. Он использует встроенный механизм заполнения данных при создании нового объекта. Рассмотрим по шагам, как это реализовать.

В форме «Стеллажа» (откуда открываем) нам достаточно передать структуру в параметре ЗначениеЗаполнения. Посмотрим на пример кода:


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

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

Способ 2. Прямое присвоение в процедуре ПриСозданииНаСервере

Если по каким-то причинам вы не хотите использовать стандартный механизм или вам требуется сложная логика проверки, можно передать ссылку через произвольный параметр и присвоить ее вручную. Выясним, как это сделать правильно.

В форме источника (Стеллаж):


&НаКлиенте
Процедура СоздатьДетальВручную(Команда)
    
    ПараметрыФормы = Новый Структура;
    ПараметрыФормы.Вставить("ПереданныйВладелец", Объект.Ссылка);
    
    ОткрытьФорму("Справочник.Деталь.ФормаОбъекта", ПараметрыФормы);
    
КонецПроцедуры

В форме приемника (Деталь) в модуле формы:


&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
    
    // Проверяем, передан ли параметр и является ли объект новым
    Если Параметры.Свойство("ПереданныйВладелец") И Объект.Ссылка.Пустая() Тогда
        Объект.Владелец = Параметры.ПереданныйВладелец;
    КонецЕсли;
    
КонецПроцедуры

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

Способ 3. Передача владельца формы (Owner)

Проанализируем еще один нюанс. У метода ОткрытьФорму есть четвертый параметр — Владелец. Важно понимать разницу: это владелец окна формы, а не владелец объекта базы данных.

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


// ЭтаФорма здесь выступает владельцем окна
ОткрытьФорму("Справочник.Деталь.ФормаОбъекта", ПараметрыФормы, ЭтаФорма);

Нюанс с незаписанными объектами

Часто возникает ситуация, когда пользователь создал «Стеллаж», еще не записал его, но уже хочет добавить «Деталь». Разберем этот момент подробнее. В 1С нельзя назначить владельцем объект, который еще не существует в базе данных (у которого Ссылка.Пустая() истинно).

Поэтому перед открытием формы детали крайне рекомендуется проверить, записан ли владелец. Проанализируем код проверки:


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

Работа с событием ОбработкаЗаполнения в модуле объекта

Для создания чистого кода и следования стандартам разработки 1С, рекомендуется выносить логику заполнения в Модуль объекта. Когда вы передаете структуру ЗначениеЗаполнения в ОткрытьФорму, в модуле объекта справочника «Деталь» срабатывает событие ОбработкаЗаполнения.

Посмотрим на пример в модуле объекта «Деталь»:


Процедура ОбработкаЗаполнения(ДанныеЗаполнения, ТекстЗаполнения, СтандартнаяОбработка)
    
    Если ТипЗнч(ДанныеЗаполнения) = Тип("Структура") Тогда
        Если ДанныеЗаполнения.Свойство("Владелец") Тогда
            Владелец = ДанныеЗаполнения.Владелец;
        КонецЕсли;
    КонецЕсли;
    
КонецПроцедуры

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

Резюме

Мы рассмотрели несколько способов передачи владельца. Подведем итог:

← На главную