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

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

При переходе на управляемое приложение разработчики часто сталкиваются с фундаментальным отличием от обычных форм: каждая управляемая форма живет в своем собственном контексте. Если в обычном приложении можно было создать переменную в модуле обработки и обращаться к ней из любой формы, то в управляемом интерфейсе вызов ОткрытьФорму для одной и той же обработки часто приводит к созданию разных экземпляров объекта на сервере. Это делает невозможным простое использование реквизитов объекта как "глобальных переменных".

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

Способ 1. Использование временного хранилища (Рекомендуемый)

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

Разберем реализацию по шагам:

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

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


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

&НаСервере
Функция ПоместитьДанныеВХранилищеНаСервере()
    // МояСтруктура — это реквизит формы или сформированные данные
    Возврат ПоместитьВоВременноеХранилище(МояСтруктура, ЭтаФорма.УникальныйИдентификатор);
КонецФункции

Теперь проанализируем, как получить эти данные во второй форме в процедуре ПриСозданииНаСервере:


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

Способ 2. Использование параметров формы

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

Проанализируем ситуацию: когда мы открываем форму, мы можем передать в нее любые данные через структуру параметров. В вызываемой форме эти параметры доступны в процедуре ПриСозданииНаСервере. Однако стоит помнить, что параметры, которые не определены в метаданных формы как "Ключевые", живут только во время выполнения этой процедуры.

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

Недостаток: Если данных много (большие таблицы, вложенные структуры), это приведет к избыточному трафику между клиентом и сервером при открытии формы.

Способ 3. Доступ через владельца формы (Клиентский вариант)

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

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

Пример кода на клиенте в подчиненной форме:


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

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

Способ 4. Глобальные переменные в клиентских общих модулях

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

Рассмотрим алгоритм:

  1. Создаем общий модуль, например, ГлобальныйКонтекстКлиент.
  2. Устанавливаем свойства: "Клиент (управляемое приложение)".
  3. В тексте модуля объявляем переменную с ключевым словом Экспорт.

Пример кода в общем модуле:

Перем ОбщаяСтруктураДанных Экспорт;

Теперь из любой формы обработки мы можем написать: ГлобальныйКонтекстКлиент.ОбщаяСтруктураДанных = Новый Структура;.

Важно понимать: эта переменная будет видна только в клиентском коде. При переходе на сервер (в процедуры &НаСервере) эта переменная будет недоступна. Для передачи этих данных на сервер их все равно придется передавать через параметры процедур или временное хранилище.

Способ 5. Использование параметров сеанса

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

Проанализируем этот вариант: параметры сеанса поддерживают ограниченный набор типов. Чтобы хранить там произвольную структуру, ее придется сериализовать в ХранилищеЗначения. Это создает накладные расходы на упаковку/распаковку данных при каждом обращении. В рамках одной обработки этот способ обычно считается избыточным и менее производительным, чем использование ВременногоХранилища с привязкой к УникальныйИдентификатор формы.

Сводная таблица и рекомендации

Подведем итог, какой метод выбрать в зависимости от ваших целей:

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

← На главную