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