Как передать значение переменной из модуля формы в модуль объекта внешней обработки в 1С 8.3

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

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

Почему переменные формы не видны в модуле объекта

Проанализируем внутреннее устройство управляемой формы. В клиент-серверной архитектуре управляемого приложения действуют жесткие правила изоляции данных:

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

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

Способ 1. Передача значения через параметры экспортного метода модуля объекта

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

В модуле объекта внешней обработки объявляем процедуру:


Процедура ВыполнитьДействиеСПараметром(Знач МояПеременная) Экспорт
    // Здесь переменная доступна и содержит переданное значение
    Сообщить("Получено значение в объекте: " + МояПеременная);
    
    // Выполняем требуемые алгоритмы обработки
    // ...
КонецПроцедуры

В модуле формы (в серверной процедуре) получаем объект обработки через штатное преобразование и вызываем созданный метод:


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

&НаКлиенте
Процедура КомандаВыполнить(Команда)
    ВыполнитьАлгоритмНаСервере();
КонецПроцедуры

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

Способ 2. Использование реквизитов метаданных внешней обработки

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

Разберем порядок действий:

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

Посмотрим на пример кода в модуле формы:


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

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

В модуле объекта к этому реквизиту можно обращаться напрямую через ЭтотОбъект.СохраненноеЗначение или просто по имени реквизита в любых методах объекта.

Способ 3. Передача через свойство ДополнительныеСвойства в рамках одного вызова

Объект внешней обработки обладает свойством ДополнительныеСвойства (имеет тип Структура). Если не хочется заводить реквизит в метаданных, но объекту требуются вспомогательные данные, передадим их через эту структуру внутри серверной процедуры.

Посмотрим на пример реализации в модуле формы:


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

В модуле объекта считываем установленное свойство:


Процедура ОбработатьДанные() Экспорт
    Если ДополнительныеСвойства.Свойство("МойПараметр") Тогда
        Значение = ДополнительныеСвойства.МойПараметр;
        Сообщить("Успешно прочитано: " + Значение);
    КонецЕсли;
КонецПроцедуры

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

Способ 4. Передача сложных структур через временное хранилище

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

В модуле формы помещаем данные в хранилище и передаем адрес в объект:


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

В модуле объекта извлекаем переданные данные по адресу:


Процедура ВыполнитьДействиеПоАдресу(АдресХранилища) Экспорт
    Данные = ПолучитьИзВременногоХранилища(АдресХранилища);
    Если ТипЗнч(Данные) = Тип("Структура") Тогда
        Сообщить("Данные получены: " + Данные.Текст);
    КонецЕсли;
КонецПроцедуры

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

← На главную