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

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

При разработке внешних обработок в среде 1С:Предприятие 8.3 (Управляемые формы) программисты часто сталкиваются с ситуацией, когда полученная ссылка на документ «исчезает» при попытке обратиться к ней из другой процедуры. Рассмотрим типичный сценарий: обработка запускается из формы документа, получает ссылку в процедуре ВыполнитьКоманду, записывает её в реквизит, но при последующем обращении этот реквизит оказывается пустым.

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

Выясняем причину: почему данные в ЭтотОбъект не сохраняются?

Разберем ситуацию, описанную пользователем. При использовании механизма дополнительных отчетов и обработок (БСП) управление обычно передается в экспортную процедуру ВыполнитьКоманду. Автор пытается сохранить ссылку в реквизит обработки следующим образом:


Процедура ВыполнитьКоманду(ИдентификаторКоманды, ОбъектыНазначенияМассив) Экспорт
    ЭтотОбъект.СсылкаНаДокумент = ОбъектыНазначенияМассив[0];
КонецПроцедуры

Главная ошибка здесь заключается в непонимании жизненного цикла серверного объекта обработки в управляемом приложении. Проанализируем, что происходит на стороне сервера:

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

Именно поэтому использование ЭтотОбъект для хранения состояния в управляемых формах (УФ) не работает так, как в обычных формах.

Решение 1: Использование реквизитов формы

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

Рассмотрим пошагово, как это реализовать:

  1. Перейдите в редактор управляемой формы обработки на закладку «Реквизиты».
  2. Добавьте новый реквизит (не путайте с реквизитами самого объекта обработки на закладке «Основные»). Назовем его ДокументСсылкаДляРаботы.
  3. Установите тип этого реквизита, соответствующий вашему документу (например, ДокументСсылка.РеализацияТоваровУслуг) или универсальный тип ЛюбаяСсылка.
  4. В коде процедуры ВыполнитьКоманду обращайтесь к этому реквизиту напрямую (если код в модуле формы) или через объект формы.

Пример кода в модуле формы:


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

&НаКлиенте
Процедура ВыполнитьДополнительноеДействие()
    Если ЗначениеЗаполнено(ДокументСсылкаДляРаботы) Тогда
        Сообщить("Работаем с документом: " + Строка(ДокументСсылкаДляРаботы));
    Иначе
        Сообщить("Ссылка потеряна!");
    КонецЕсли;
КонецПроцедуры

Решение 2: Клиентские переменные модуля формы

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

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

Пример реализации:


&НаКлиенте
Перем СсылкаНаДокументКэш;

&НаКлиенте
Процедура ВыполнитьКоманду(ИдентификаторКоманды, ОбъектыНазначенияМассив) Экспорт
    СсылкаНаДокументКэш = ОбъектыНазначенияМассив[0];
КонецПроцедуры

&НаКлиенте
Процедура ДругаяПроцедураНаКлиенте()
    // Здесь СсылкаНаДокументКэш будет доступна
    Если СсылкаНаДокументКэш <> Неопределено Тогда
        // Действие
    КонецЕсли;
КонецПроцедуры

Важное замечание: Если вы объявите переменную просто как Перем СсылкаНаДок; без директивы &НаКлиенте, она будет считаться серверной. Серверные переменные модуля формы живут еще меньше клиентских — они очищаются сразу после завершения серверного вызова. Для сохранения состояния между вызовами сервера они не подходят.

Решение 3: Получение ссылки через Параметры формы (БСП)

Если ваша обработка написана по стандартам БСП (Библиотеки Стандартных Подсистем), то при открытии формы массив объектов назначения часто передается в параметрах системы. Рассмотрим, как правильно перехватить ссылку в процедуре ПриСозданииНаСервере.

Это «элегантный» способ, который позволяет заполнить реквизиты формы еще в момент инициализации, не дожидаясь явного вызова команды пользователем.


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

Подведем итоги и выберем лучший вариант

Мы проанализировали три способа сохранения ссылки. Выбор зависит от архитектуры вашей задачи:

  1. Реквизит формы (в дереве реквизитов) — самый надежный и рекомендуемый метод. Данные доступны и на клиенте, и на сервере. Платформа берет на себя все заботы по передаче (сериализации) значения.
  2. Клиентская переменная модуля — подходит для временного кэширования данных, которые не нужны серверу. Экономит трафик между клиентом и сервером, но требует осторожности при контекстных вызовах.
  3. Параметры формы — лучший способ инициализации обработки, вызываемой из списков или форм документов через подсистему «Дополнительные отчеты и обработки».

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

← На главную