При разработке в среде 1С:Предприятие 8.3 на управляемых формах часто возникает задача: сформировать тяжелые данные (например, отчет, расчет или таблицу подбора) на сервере в контексте одной формы и передать их в серверный модуль другой открытой формы. При этом передавать весь массив или таблицу через клиент крайне неэффективно, а сам тип ТаблицаЗначений на клиенте и вовсе недоступен.
Разберем подробно, как правильно помещать коллекции во временное хранилище, управлять временем их жизни и асинхронно передавать адрес между формами без использования устаревших модальных вызовов.
Рассмотрим распространенное заблуждение начинающих разработчиков. Часто таблицу значений пытаются вручную свернуть в массив структур, полагая, что временное хранилище не поддерживает таблицы.
Посмотрим на пример такого ручного преобразования:
// Избыточное преобразование перед сохранением во временное хранилище
рМассив = Новый Массив;
Для Каждого Строка Из мТаблица Цикл
Запись = Новый Структура;
Запись.Вставить("Реквизиты", Строка.Реквизиты);
Запись.Вставить("Номер", Строка.Номер);
рМассив.Добавить(Запись);
КонецЦикла;
Важно понимать: ограничение на использование типа ТаблицаЗначений действует исключительно на стороне тонкого и веб-клиента. В контексте сервера во временное хранилище можно напрямую передавать полноценную таблицу значений: ПоместитьВоВременноеХранилище(мТаблица, УникальныйИдентификатор). Преобразовывать её в массив структур не требуется, если сама таблица не возвращается непосредственно в клиентский контекст.
Проанализируем работу функции ПоместитьВоВременноеХранилище(). У нее есть два варианта вызова:
Адрес = ПоместитьВоВременноеХранилище(Данные); — в этом случае данные привязываются к текущему серверному контексту и удаляются сразу после завершения текущего вызова с клиента. Передать такой адрес в другую форму или использовать в следующем серверном вызове не удастся.Адрес = ПоместитьВоВременноеХранилище(Данные, УникальныйИдентификатор); — данные связываются с сеансом жизни конкретной формы и будут доступны до тех пор, пока эта форма остается открытой, либо пока данные не будут удалены принудительно.После считывания и обработки данных на сервере хорошей практикой является освобождение оперативной памяти вызовом УдалитьИзВременногоХранилища(Адрес).
Разберем по шагам типовой асинхронный сценарий: из основной формы открывается форма отчета/подбора, формирует данные на сервере, помещает их во временное хранилище и возвращает только короткую строку адреса в основную форму.
УникальныйИдентификатор.
&НаКлиенте
Процедура ОткрытьФормуПодбора(Команда)
Оповещение = Новый ОписаниеОповещения("ПослеЗакрытияФормыПодбора", ЭтаФорма);
ПараметрыОткрытия = Новый Структура;
ПараметрыОткрытия.Вставить("ИдентификаторВладельца", ЭтаФорма.УникальныйИдентификатор);
ОткрытьФорму("Отчет.МТ_ОстаткиТоваровНаСкладах.Форма.Форма", ПараметрыОткрытия, ЭтаФорма, , , , Оповещение);
КонецПроцедуры
&НаСервере
Функция СформироватьДанныеНаСервере()
// Создаем или получаем нужную таблицу значений напрямую на сервере
ТаблицаРезультат = Новый ТаблицаЗначений;
ТаблицаРезультат.Колонки.Добавить("Номер", Новый ОписаниеТипов("Число"));
ТаблицаРезультат.Колонки.Добавить("Реквизиты", Новый ОписаниеТипов("Строка"));
// Заполняем таблицу значениями...
// Помещаем в хранилище с привязкой к вызывающей форме
ИдентификаторФормы = Параметры.ИдентификаторВладельца;
Возврат ПоместитьВоВременноеХранилище(ТаблицаРезультат, ИдентификаторФормы);
КонецФункции
&НаКлиенте
Процедура СформироватьИЗакрыть(Команда)
АдресХранилища = СформироватьДанныеНаСервере();
// Закрываем форму и возвращаем только строковый адрес
ЭтаФорма.Закрыть(АдресХранилища);
КонецПроцедуры
&НаКлиенте
Процедура ПослеЗакрытияФормыПодбора(РезультатЗакрытия, ДополнительныеПараметры) Экспорт
Если РезультатЗакрытия = Неопределено Тогда
Возврат;
КонецЕсли;
// РезультатЗакрытия содержит строку АдресХранилища
ОбработатьРезультатНаСервере(РезультатЗакрытия);
КонецПроцедуры
&НаСервере
Процедура ОбработатьРезультатНаСервере(Знач АдресХранилища)
// Извлекаем таблицу значений или массив на сервере
Таблица = ПолучитьИзВременногоХранилища(АдресХранилища);
Если Таблица <> Неопределено Тогда
// Выполняем требуемые действия с таблицей значений
Для Каждого Строка Из Таблица Цикл
// Логика обработки
КонецЦикла;
// Очищаем хранилище после использования
УдалитьИзВременногоХранилища(АдресХранилища);
КонецЕсли;
КонецПроцедуры
Если задача противоположная — передать готовую таблицу значений из текущей формы во вновь создаваемую форму:
ПоместитьВоВременноеХранилище(Таблица, ЭтаФорма.УникальныйИдентификатор).ОткрытьФорму(): ПараметрыОткрытия.Вставить("АдресДанных", Адрес).ПриСозданииНаСервере(Отказ, СтандартнаяОбработка) извлекаем данные: Таблица = ПолучитьИзВременногоХранилища(Параметры.АдресДанных).Такой подход исключает сериализацию тяжелых таблиц значений в клиенто-серверных вызовах и обеспечивает корректную работу конфигурации в режиме без модальных окон.