Почему при нажатии «Записать и закрыть» возвращается Неопределено и как получить ссылку на объект

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

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

Выясним причину: почему платформа возвращает Неопределено

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

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

Способ 1: Использование метода Закрыть с параметром

Это самый прямой путь решения проблемы. Нам нужно перехватить процесс закрытия и передать в метод Закрыть() ссылку на записанный объект. Разберем по шагам, как это реализовать.

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


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

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


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

Способ 2: Механизм глобальных оповещений

Рассмотрим ситуацию, когда нам не совсем удобно полагаться на результат закрытия формы. Например, пользователь может нажать «Записать», поработать в форме еще 10 минут, а потом просто закрыть ее. В этом случае лучше использовать метод Оповестить().

Этот способ позволяет передать данные в родительскую форму в любой момент, например, сразу после записи объекта. В модуле открываемой формы в событии ПослеЗаписи добавим код:


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

В основной (вызывающей) форме нам нужно реализовать обработчик ОбработкаОповещения. Посмотрим на пример:


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

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

Способ 3: Режим выбора и ОповеститьОВыборе

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

В открываемой форме в обработчике команды записи или специальной кнопки выбора мы используем метод ОповеститьОВыборе(). Разберем ситуацию:


&НаКлиенте
Процедура КомандаВыбрать(Команда)
    // Метод передает значение владельцу формы или в ОбработкаВыбора
    ОповеститьОВыборе(Объект.Ссылка);
КонецПроцедуры

Если при открытии формы в параметре Владелец была указана вызывающая форма, то ссылка вернется в процедуру ОбработкаВыбора вызывающей формы. Это стандартный и очень "чистый" с точки зрения архитектуры 1С способ.

Особенности работы с новыми объектами

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

Проанализируем правильный алгоритм действий для новых документов или справочников:

  1. Пользователь нажимает кнопку завершения действия.
  2. Выполняется серверная процедура записи (ЗаписатьНаСервере или стандартный метод Записать()).
  3. Только после успешной записи на сервере Объект.Ссылка становится валидной.
  4. Передаем эту ссылку в метод Закрыть(Ссылка) или Оповестить().

Рассмотрим пример в модуле формы, который гарантирует получение ссылки после записи на сервере:


&НаСервере
Процедура ПослеЗаписиНаСервере(ТекущийОбъект, ПараметрыЗаписи)
    // Ссылка уже доступна в ТекущийОбъект.Ссылка
    // Можно сохранить её в переменную модуля формы, если нужно использовать позже
    СохраненнаяСсылка = ТекущийОбъект.Ссылка;
КонецПроцедуры

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

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

← На главную