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

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

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

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

Причины возникновения ошибок и особенности платформы

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

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

Шаг 1. Передача параметров при открытии второй формы

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

Посмотрим на пример кода в первой форме обработки (например, при нажатии команды открытия настройки или подбора):


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

Шаг 2. Прием и сохранение параметров в открываемой форме

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

Чтобы данные не терялись между серверными вызовами при нажатии кнопок в подчиненной форме, добавим на вкладке Реквизиты этой формы новые реквизиты:

  1. ДатаДокумента с типом Дата;
  2. ДокументСсылка с типом ссылки на соответствующий документ (или ДокументСсылка / ЛюбаяСсылка).

В модуле открываемой формы в процедуре ПриСозданииНаСервере считываем переданные параметры и записываем их в созданные реквизиты формы:


&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
    
    // Считываем дату документа
    Если Параметры.Свойство("ДатаДокумента", ДатаДокумента) Тогда
        // Реквизит формы ДатаДокумента инициализирован переданным значением
    КонецЕсли;
    
    // Считываем ссылку на документ
    Если Параметры.Свойство("ДокументСсылка", ДокументСсылка) Тогда
        // Реквизит формы ДокументСсылка инициализирован переданным значением
    КонецЕсли;
    
КонецПроцедуры

Теперь в любой серверной процедуре открытой формы (например, при расчете или заполнении) значения ДатаДокумента и ДокументСсылка будут доступны и сохранят свое состояние:


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

&НаСервере
Процедура ЗаполнитьНаСервере()
    // Значения реквизитов формы доступны и не сбрасываются в Неопределено
    Сообщение = Новый СообщениеПользователю;
    Сообщение.Текст = "Обрабатываем документ: " + Строка(ДокументСсылка) + " от " + Строка(ДатаДокумента);
    Сообщение.Сообщить();
КонецПроцедуры

Шаг 3. Возврат результата работы в основную форму

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


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

В вызывающей форме результат перехватывается экспортируемой клиентской процедурой, которая была указана в объекте ОписаниеОповещения:


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

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

← На главную