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

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

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

Выясним причину: почему данные «очищаются»?

Проанализируем типичную ошибку. Когда мы вызываем метод ОткрытьФорму("ВнешняяОбработка.Имя.Форма.ФормаНастроек"), платформа 1С создает новый экземпляр объекта обработки. Несмотря на то, что у вас уже открыта основная форма этой же обработки, система не «знает» автоматически, что вы хотите использовать тот же самый набор данных. В результате в новой форме реквизит Объект.ПутьКФайлу будет пустым, так как это реквизит совершенно нового, только что созданного в памяти сервера объекта.

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

Способ 1. Использование временного хранилища для передачи целого объекта

Если ваша обработка содержит много реквизитов и вам нужно передать их все сразу «как есть», наиболее правильным методом будет использование временного хранилища. Рассмотрим этот процесс по шагам.

Шаг 1. В основной форме подготавливаем данные к передаче.

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


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

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

Шаг 2. В открываемой форме принимаем данные.

В процедуре ПриСозданииНаСервере формы настроек мы извлекаем объект по переданному адресу и заполняем локальный реквизит Объект.


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

Способ 2. Передача конкретных значений через параметры формы

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

Разберем ситуацию: нам нужно передать ПутьКФайлу в форму настроек и получить его измененным обратно. В основной форме при вызове открытия формы укажем параметр:


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

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

В форме настроек в процедуре ПриСозданииНаСервере просто считываем значение из Параметры.ТекущийПуть и присваиваем реквизиту формы.

Способ 3. Механизм оповещений (Оповестить и ОбработкаОповещения)

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

В форме настроек (при нажатии кнопки «Применить» или при изменении реквизита):


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

В основной форме создадим обработчик события ОбработкаОповещения:


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

Способ 4. Хранилище общих настроек (для постоянного сохранения)

Если задача стоит так, чтобы настройки сохранялись даже после того, как пользователь полностью закрыл 1С и открыл ее на следующий день, следует использовать системный механизм ХранилищеОбщихНастроек. Это особенно актуально для внешних обработок, так как у них нет записи в базе данных, где можно было бы хранить значения.

Сохранение данных:


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

Восстановление данных (например, в ПриСозданииНаСервере):


&НаСервере
Процедура ВосстановитьНастройки()
    Настройки = ХранилищеОбщихНастроек.Загрузить("ВнешняяОбработка_ПечатьЧеков", "ПользовательскиеНастройки");
    Если Настройки <> Неопределено Тогда
        ЗаполнитьЗначенияСвойств(Объект, Настройки);
    КонецЕсли;
КонецПроцедуры

Важные нюансы и рекомендации

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

  1. Ключ уникальности формы. При вызове ОткрытьФорму вы можете передать четвертый параметр — КлючУникальности. Если вы будете открывать форму с одним и тем же ключом, система не будет плодить новые окна, а вернет уже открытую форму. Это предотвращает рассинхронизацию данных из-за множества открытых копий одной и той же настройки.
  2. Автоматическое сохранение данных в настройках. У управляемой формы есть свойства СохранениеДанныхВНастройках и АвтоматическоеСохранениеДанныхВНастройках. Если их включить, а в списке «Сохраняемые реквизиты» отметить нужные поля, платформа сама будет запоминать их значения для каждого пользователя. Это самый простой способ «без кода», но он работает только внутри конкретной формы.
  3. Обновление отображения. Иногда данные в Объекте на сервере уже изменились, но на клиенте форма «замерла». В таких случаях в основной форме помогает вызов метода ОбновитьОтображениеДанных(), который заставляет интерфейс перечитать текущие значения реквизитов.

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

← На главную