Как получить ссылку на созданный элемент при закрытии формы без изменения её кода

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

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

Выясним причину проблемы

Для начала проанализируем ситуацию. Когда мы открываем форму программно и указываем ОписаниеОповещения, платформа ожидает, что при закрытии формы в метод Закрыть() будет передан какой-то параметр. Однако стандартные команды формы объекта, такие как Записать и закрыть, вызывают метод Закрыть() без параметров. Поскольку форма объекта "не знает", что её вызвали с ожиданием результата, переменная РезультатЗакрытия в вашей процедуре оповещения всегда будет оставаться пустой.

Если мы не можем менять код формы (например, форма типовая или находится в расширении, которое не хочется перегружать), нам нужно использовать стандартные механизмы платформы, которые заставляют форму возвращать значение принудительно.

Решение через использование Режима выбора

Самый эффективный и "чистый" способ получить ссылку — это имитировать выбор объекта. Платформа 1С:Предприятие 8 спроектирована так, что если форма открыта в режиме выбора, то при записи нового объекта или выборе существующего она автоматически возвращает ссылку владельцу. Рассмотрим подробнее, как это реализовать.

Для этого при вызове функции ОткрытьФорму необходимо передать параметр РежимВыбора со значением Истина. В этом случае результат будет возвращен не в ОписаниеОповещения, а в стандартное событие вызывающей формы — ОбработкаВыбора.

Посмотрим на пример реализации кода в вызывающей форме:


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

    // Открываем форму. Владельцем указываем "ЭтаФорма", 
    // чтобы сработало событие ОбработкаВыбора
    ОткрытьФорму("Справочник.Модели.Форма.ФормаЭлемента", 
                 ПараметрыОткрытия, 
                 ЭтаФорма, 
                 Истина); // Уникальность ключа (по желанию)

КонецПроцедуры

После того как пользователь нажмет кнопку Записать и закрыть в открытой форме, в исходной форме сработает стандартный обработчик ОбработкаВыбора. Рассмотрим его структуру:


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

Нюансы заполнения параметров

Разберем важный момент: как правильно передать данные для заполнения в новую форму, если мы не используем прямое обращение к ОткрытаяФорма.Объект. Как было отмечено в обсуждении, использование ЗаполнитьЗначенияСвойств для ОткрытаяФорма.Объект на клиенте может работать некорректно или приводить к ошибкам прав доступа.

Правильный подход — использование параметра ЗначенияЗаполнения. Платформа автоматически передает эту структуру в обработчик ОбработкаЗаполнения в модуле объекта.

Важно помнить:

  1. Реквизиты объекта будут заполнены автоматически, если у них в конфигураторе установлено свойство Заполнять из данных заполнения.
  2. Если для реквизита "Наименование" автоматическое заполнение не отрабатывает, можно попробовать передать параметр ТекстЗаполнения.
  3. Для сложных случаев заполнения (когда нужно заполнить табличные части или программно вычислить значения) лучше использовать параметр Основание, передавая туда структуру или ссылку, и обрабатывать её в модуле объекта.

Альтернативный подход через ОбработкаОповещения

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

При записи любого объекта платформа генерирует системное событие оповещения об изменении. Мы можем "поймать" его в вызывающей форме. Для этого:

  1. В вызывающей форме опишем обработчик ОбработкаОповещения.
  2. При открытии формы нового элемента запомним какой-либо идентификатор (например, уникальный ключ в структуре ПараметрыОткрытия).

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

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

Подведем итоги

Мы рассмотрели, что стандартное ОписаниеОповещения не возвращает ссылку из формы объекта просто потому, что форма не запрограммирована её возвращать. Вместо попыток "взломать" логику закрытия, мы использовали штатный механизм РежимВыбора = Истина. Это решение позволяет:

Используя этот подход, вы сможете эффективно интегрировать создание новых объектов в свои интерфейсные решения, обеспечивая бесшовный опыт для конечного пользователя.

← На главную