Почему при создании группы справочника через ОткрытьФорму с параметром Основание всегда создается элемент

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

В практике разработки на платформе 1С:Предприятие 8.3 часто возникает задача программного открытия формы нового объекта с предварительным заполнением данных. Казалось бы, механизмы платформы универсальны, но при работе с иерархическими справочниками разработчики часто натыкаются на "подлянку": при попытке создать группу на основании другого объекта система упорно создает элемент. Давайте подробно разберем, почему так происходит, и как правильно реализовать эту задачу, чтобы пользователь увидел готовую к записи форму группы с заполненными реквизитами.

Суть проблемы: конфликт параметров в функции ОткрытьФорму

Рассмотрим ситуацию: у нас есть справочник с иерархией групп и элементов. Мы хотим программно открыть форму новой группы, передав в нее объект-основание для заполнения. Типичный код, который кажется логичным, выглядит так:


ПараметрыФормы = Новый Структура;
ПараметрыФормы.Вставить("Основание", ОбъектОснование);
ПараметрыФормы.Вставить("ЭтоГруппа", Истина);

ОткрытьФорму("Справочник.НашСправочник.ФормаГруппы", ПараметрыФормы, Форма);

Проанализируем, что происходит "под капотом" платформы. Несмотря на явное указание ПараметрыФормы.Вставить("ЭтоГруппа", Истина) и вызов именно ФормаГруппы, система инициализирует новый объект как элемент. Выясним причину: в платформе заложен жесткий приоритет параметра Основание. Как только система видит этот ключ, она запускает стандартный механизм "Заполнить на основании". Исторически этот механизм в 1С ориентирован на создание элементов данных. Платформа создает экземпляр СправочникОбъект, устанавливая ему тип "Элемент" еще до того, как управление передается в программный код модуля или формы.

Самое неприятное в этой ситуации то, что свойство ЭтоГруппа является доступным только для чтения после инициализации объекта. Если мы попробуем исправить ситуацию в процедуре ОбработкаЗаполнения модуля объекта, у нас ничего не получится — платформа просто не позволит изменить тип уже созданного в памяти объекта с элемента на группу.

Решение №1: Использование структуры ЗначенияЗаполнения

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

Разберем по шагам, как переписать код:

  1. Создадим структуру, в которую поместим все необходимые данные из объекта-основания.
  2. Передадим эту структуру в параметр ЗначенияЗаполнения.
  3. Обязательно укажем флаг ЭтоГруппа = Истина.

Посмотрим на пример реализации:


// 1. Формируем структуру данных для заполнения
ДанныеДляЗаполнения = Новый Структура;
ДанныеДляЗаполнения.Вставить("Родитель", СсылкаНаРодителя);
ДанныеДляЗаполнения.Вставить("Наименование", "Новая группа на основании " + ОбъектОснование.Наименование);
// Добавляем любые другие реквизиты, которые должны быть в группе
ДанныеДляЗаполнения.Вставить("Ответственный", ОбъектОснование.Ответственный);

// 2. Подготавливаем параметры открытия формы
ПараметрыФормы = Новый Структура;
ПараметрыФормы.Вставить("ЗначенияЗаполнения", ДанныеДляЗаполнения);
ПараметрыФормы.Вставить("ЭтоГруппа", Истина); // Теперь этот флаг будет отработан корректно

// 3. Открываем форму
ОткрытьФорму("Справочник.УП_КаталогПредметовЗакупкиЗаявка.ФормаГруппы", ПараметрыФормы);

При таком подходе платформа видит, что создается именно группа (благодаря ЭтоГруппа), и корректно заполняет ее реквизиты из переданной структуры.

Решение №2: Эмуляция заполнения на основании при сложной логике

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

Проанализируем этот алгоритм:

  1. Создаем объект группы в памяти без записи.
  2. Вызываем метод Заполнить(), передавая в него основание.
  3. Выгружаем заполненные реквизиты объекта в структуру.
  4. Передаем структуру в ОткрытьФорму.

Пример кода для реализации такого подхода:


// Создаем временный объект группы
НоваяГруппаОбъект = Справочники.УП_КаталогПредметовЗакупкиЗаявка.СоздатьГруппу();
// Вызываем стандартную логику заполнения на основании
НоваяГруппаОбъект.Заполнить(ОбъектОснование);

// Копируем данные в структуру для передачи в форму
ДанныеЗаполнения = Новый Структура;
Для Каждого Реквизит Из НоваяГруппаОбъект.Метаданные().Реквизиты Цикл
    ДанныеЗаполнения.Вставить(Реквизит.Имя, НоваяГруппаОбъект[Реквизит.Имя]);
КонецЦикла;
ДанныеЗаполнения.Вставить("Наименование", НоваяГруппаОбъект.Наименование);
ДанныеЗаполнения.Вставить("Родитель", НоваяГруппаОбъект.Родитель);

ПараметрыФормы = Новый Структура;
ПараметрыФормы.Вставить("ЗначенияЗаполнения", ДанныеЗаполнения);
ПараметрыФормы.Вставить("ЭтоГруппа", Истина);

ОткрытьФорму("Справочник.УП_КаталогПредметовЗакупкиЗаявка.ФормаГруппы", ПараметрыФормы);

Важные нюансы и выводы

Разберем несколько важных моментов, которые стоит учитывать при работе с ОткрытьФорму:

Таким образом, мы выяснили, что сочетание параметров Основание и ЭтоГруппа = Истина в методе ОткрытьФорму является конфликтным. Платформа 1С всегда отдает приоритет созданию элемента при наличии основания. Для корректного создания группы "на основании" следует всегда использовать параметр ЗначенияЗаполнения, передавая в него либо вручную собранную структуру, либо структуру, полученную из предварительно созданного в памяти объекта группы.

← На главную