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