Разработка и Конфигурация · 11 мин
Передача таблицы значений с сервера на клиент в 1С через временное хранилище
Как передать таблицу значений с сервера на клиент в 1С через временное хранилище: ПоместитьВоВременноеХранилище, адрес, ПолучитьИзВременногоХранилища, примеры кода.
Таблица значений — один из самых используемых типов данных в 1С, но у него есть важное ограничение: объект типа «ТаблицаЗначений» нельзя напрямую вернуть с сервера на клиент в управляемом приложении. При попытке сделать это платформа выдаст ошибку о недопустимом типе параметра или возвращаемого значения серверной процедуры. Стандартное решение — поместить таблицу во временное хранилище на сервере и передать клиенту только адрес (строку), по которому данные можно получить и преобразовать обратно.
Механизм временного хранилища встроен в платформу и не требует никаких дополнительных настроек. Разработчику достаточно вызвать функцию ПоместитьВоВременноеХранилище на сервере, вернуть полученный адрес на клиент, а затем забрать данные функцией ПолучитьИзВременногоХранилища в нужный момент. Такой подход работает и в управляемых формах, и в обычном приложении, и при обмене между фоновыми заданиями и основным сеансом.
В этой статье разобран полный цикл передачи: от помещения таблицы в хранилище до загрузки её в табличную часть формы, с примерами кода, типичными ошибками и вариантами, когда хранилище лучше заменить другим механизмом.
Почему таблицу значений нельзя передать напрямую
В управляемом приложении 1С набор типов, которые можно передавать между клиентом и сервером, строго ограничен. Разрешены примитивные типы (строка, число, дата, булево), структуры и массивы из допустимых типов, ссылки на объекты базы данных и некоторые сериализуемые объекты вроде табличного документа. Таблица значений в этот список не входит — это несериализуемый объект, живущий только в памяти того контекста, где он создан.
Если объявить серверную функцию, возвращающую таблицу значений, и вызвать её с клиента, платформа выдаст ошибку вида «Недопустимый тип возвращаемого значения» или «Ошибка передачи данных между клиентом и сервером». Та же проблема возникает при попытке передать таблицу как параметр с клиента на сервер.
Временное хранилище решает задачу иначе: сами данные остаются на сервере, а между контекстами передаётся только строковый адрес — допустимый для передачи тип. По этому адресу любой серверный вызов в пределах сессии может получить сохранённый объект.
Базовый сценарий: поместить таблицу и вернуть адрес
Минимальная реализация состоит из двух частей. На сервере таблица формируется и помещается в хранилище, клиенту возвращается адрес. Вторым параметром ПоместитьВоВременноеХранилище рекомендуется передавать УникальныйИдентификатор формы — тогда данные будут жить, пока открыта форма, и автоматически удалятся при её закрытии.
&НаСервере
Функция СформироватьТаблицуНаСервере()
Таблица = Новый ТаблицаЗначений;
Таблица.Колонки.Добавить("Номенклатура");
Таблица.Колонки.Добавить("Количество");
Запрос = Новый Запрос("ВЫБРАТЬ ПЕРВЫЕ 100 Ссылка КАК Номенклатура,
| 1 КАК Количество ИЗ Справочник.Номенклатура");
Таблица = Запрос.Выполнить().Выгрузить();
Адрес = ПоместитьВоВременноеХранилище(Таблица, УникальныйИдентификатор);
Возврат Адрес;
КонецФункции
&НаКлиенте
Процедура ЗагрузитьДанные(Команда)
Адрес = СформироватьТаблицуНаСервере();
// Адрес — строка вида "e1cib/tempstorage/..."
ЗагрузитьТаблицуИзХранилища(Адрес);
КонецПроцедуры
Обратите внимание: клиентская процедура получила только строку адреса. Сам объект таблицы на клиенте недоступен — для работы с ним потребуется ещё один серверный вызов, который извлечёт данные и загрузит их в реквизит формы допустимого типа, например в динамический список или таблицу значений формы.
- 1На сервере сформируйте таблицу значений (запрос, расчёт, обработка).
- 2Вызовите ПоместитьВоВременноеХранилище(Таблица, УникальныйИдентификатор) и сохраните возвращённый адрес.
- 3Верните адрес на клиент как строку.
- 4В серверной процедуре формы получите таблицу через ПолучитьИзВременногоХранилища(Адрес).
- 5Загрузите данные в реквизит формы через ЗначениеВРеквизитФормы или Загрузить().
- 6Проверьте, что таблица на форме заполнена, и при необходимости очистите хранилище.
Получение таблицы из хранилища и загрузка в форму
Чтобы отобразить данные пользователю, адрес нужно передать обратно в серверный контекст, где таблица извлекается из хранилища и загружается в реквизит формы типа «ТаблицаЗначений». Для этого используется связка ПолучитьИзВременногоХранилища и ЗначениеВРеквизитФормы.
&НаСервере
Процедура ЗагрузитьТаблицуИзХранилища(Адрес)
Таблица = ПолучитьИзВременногоХранилища(Адрес);
Если ТипЗнч(Таблица) = Тип("ТаблицаЗначений") Тогда
// ТаблицаДанных — реквизит формы типа ТаблицаЗначений
ЗначениеВРеквизитФормы(Таблица, "ТаблицаДанных");
Иначе
ВызватьИсключение "По адресу нет таблицы значений";
КонецЕсли;
КонецПроцедуры
Проверка типа через ТипЗнч важна: если адрес устарел, хранилище очищено или по ошибке туда помещён другой объект, без проверки вы получите труднодиагностируемую ошибку преобразования. Если данные нужны не в форме, а в другой серверной процедуре (например, для последующей обработки), достаточно одного вызова ПолучитьИзВременногоХранилища.
Когда таблица уже не нужна, хранилище стоит освободить явно вызовом УдалитьИзВременногоХранилища(Адрес). Это особенно актуально для больших таблиц, если адрес создавался без привязки к форме — такие данные живут до конца сеанса и занимают память сервера.
Передача таблицы из фонового задания
Одна из самых частых практических задач — длительная обработка в фоновом задании, результатом которой является таблица. Здесь временное хранилище используется в связке с механизмом ДлительныеОперации: фоновое задание помещает результат по адресу, переданному в параметрах, а форма по завершении забирает данные.
// В общем модуле (сервер)
Процедура ВыполнитьЗагрузку(Параметры, АдресРезультата) Экспорт
Таблица = Новый ТаблицаЗначений;
// ... длительное формирование таблицы ...
ПоместитьВоВременноеХранилище(Таблица, АдресРезультата);
КонецПроцедуры
// В форме, обработчик завершения
&НаСервере
Процедура ОбработатьРезультатНаСервере(АдресРезультата)
Таблица = ПолучитьИзВременногоХранилища(АдресРезультата);
Если ТипЗнч(Таблица) = Тип("ТаблицаЗначений") Тогда
ЗначениеВРеквизитФормы(Таблица, "ТаблицаДанных");
КонецЕсли;
КонецПроцедуры
При таком подходе адрес результата создаётся заранее вызовом ПоместитьВоВременноеХранилище(Неопределено, УникальныйИдентификатор) и передаётся в параметры длительной операции. После обработки результата хранилище следует очистить, поскольку фоновые задания могут порождать большие объёмы данных.
Альтернативы временному хранилищу
Хранилище — не единственный способ решить задачу. В зависимости от сценария могут быть удобнее другие варианты, и выбирать стоит осознанно.
Способы передать табличные данные
Универсальный способ: таблица любой структуры, работает с фоновыми заданиями. Требует двух серверных вызовов и контроля очистки.
Если таблица нужна только на форме, серверная процедура может сразу заполнить реквизит формы — клиенту вообще ничего передавать не надо.
Допустим для передачи на клиент напрямую, если все значения — сериализуемые типы. Подходит для небольших данных, но теряются типы колонок.
ЗначениеВJSON на сервере, разбор на клиенте. Удобно для интеграций и тонкого клиента, но требует ручного описания структуры.
Упаковка в строку внутреннего формата. Работает, но строка громоздкая, а формат не предназначен для обмена между сеансами.
Если таблица нужна только для показа пользователю в текущей форме, самый простой путь — вообще обойтись без хранилища: серверная процедура формирует таблицу и сразу вызывает ЗначениеВРеквизитФормы. Хранилище оправдано, когда данные создаются вне формы (фоновое задание, другой объект) или когда результат нужно получать по требованию, а не сразу.
Типичные ошибки и как их избежать
Отдельно стоит упомянуть тонкий клиент и веб-клиент: там ограничения на передаваемые типы действуют так же, и схема с хранилищем работает идентично. Разница лишь в том, что лишние серверные вызовы на медленном канале ощутимее, поэтому стоит минимизировать их число — например, получать и загружать таблицу в одном серверном вызове, как показано в примерах выше.
Как проверить результат
Строка с адресом вида e1cib/tempstorage/...
Ошибка о недопустимом типе возвращаемого значения
ПолучитьИзВременногоХранилища возвращает ТаблицаЗначений с нужным числом строк
Возвращается Неопределено или объект другого типа
Таблица формы заполнена, колонки и типы соответствуют исходным
Пустая таблица или ошибка ЗначениеВРеквизитФормы
После УдалитьИзВременногоХранилища повторное получение даёт Неопределено
Данные остаются доступны — хранилище не очищено
FAQ
Можно ли передать таблицу значений с клиента на сервер?
Напрямую — нет, ограничение действует в обе стороны. Рабочие варианты: заполнить реквизит формы типа ТаблицаЗначений (он доступен в серверных процедурах формы через РеквизитФормыВЗначение) или собрать массив структур с простыми типами и передать его параметром.
Сколько живут данные во временном хранилище?
Если при помещении передан УникальныйИдентификатор формы — до закрытия формы. Если параметр не указан — до конца сеанса пользователя. Явно удалить данные можно в любой момент вызовом УдалитьИзВременногоХранилища.
Что вернёт ПолучитьИзВременногоХранилища, если адрес недействителен?
Функция вернёт Неопределено, если по адресу ничего нет (данные удалены, форма закрыта, адрес сформирован ошибочно). Поэтому перед использованием результата всегда делайте проверку на Неопределено и на нужный тип.
Можно ли хранить в хранилище не только таблицы?
Да, временное хранилище принимает практически любые значения: структуры, массивы, двоичные данные, табличные документы, результаты запросов. Часто туда помещают структуру, где одно из полей — таблица значений, а другие — сопутствующие параметры результата.
Доступен ли адрес хранилища из другого сеанса?
Нет, временное хранилище привязано к сеансу, в котором создано. Для обмена данными между сеансами используются другие механизмы: регистры сведений, константы, планы обмена или файлы.
Что делать, если таблица слишком большая для передачи?
Не передавайте её целиком: покажите данные через динамический список, передавайте итоги или порции строк, либо сохраните результат в регистр сведений и читайте по мере необходимости. Хранилище не предназначено для массивных выборок.
Что важно запомнить
Таблицу значений передают между сервером и клиентом только через посредника: ПоместитьВоВременноеХранилище на сервере, адрес-строка клиенту, ПолучитьИзВременногоХранилища в серверной процедуре формы. Привязывайте хранилище к УникальныйИдентификатор формы, проверяйте тип полученного значения и очищайте хранилище после использования.