Как передать результат запроса (Таблицу Значений) с сервера на клиент в 1С?

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

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

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

Способ 1. Преобразование в массив структур (Ручной метод)

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

Посмотрим на пример кода, который реализует эту логику:


&НаСервере
Функция ПолучитьДанныеЗапросаНаСервере()
    
    Запрос = Новый Запрос;
    Запрос.Текст = 
        "ВЫБРАТЬ
        |    Контрагенты.Ссылка КАК Ссылка,
        |    Контрагенты.Наименование КАК Наименование
        |ИЗ
        |    Справочник.Контрагенты КАК Контрагенты";
    
    ТаблицаЗначений = Запрос.Выполнить().Выгрузить();
    
    Массив = Новый Массив();
    СтруктураСтрокой = "";
    НужнаЗапятая = Ложь;
    
    // Формируем строку с именами колонок для создания структуры
    Для Каждого Колонка Из ТаблицаЗначений.Колонки Цикл
        Если НужнаЗапятая Тогда
            СтруктураСтрокой = СтруктураСтрокой + ",";
        КонецЕсли;
        СтруктураСтрокой = СтруктураСтрокой + Колонка.Имя;
        НужнаЗапятая = Истина;
    КонецЦикла;
    
    // Заполняем массив структурами
    Для Каждого Строка Из ТаблицаЗначений Цикл
        НоваяСтрока = Новый Структура(СтруктураСтрокой);
        ЗаполнитьЗначенияСвойств(НоваяСтрока, Строка);
        Массив.Добавить(НоваяСтрока);
    КонецЦикла;
    
    Возврат Массив;
    
КонецФункции

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

Способ 2. Использование возможностей БСП

Если в вашей конфигурации встроена Библиотека стандартных подсистем (БСП), мы настоятельно рекомендуем не писать ручные циклы, а использовать готовые инструменты, которые уже «протоптаны» разработчиками фирмы «1С».

Рассмотрим использование типовой функции. Вместо десятков строк кода достаточно вызвать:


МассивСтруктур = ОбщегоНазначения.ТаблицаЗначенийВМассив(ТаблицаЗначений);
Возврат МассивСтруктур;

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

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

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

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

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


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

При возврате на клиент этот реквизит автоматически конвертируется в служебный тип ДанныеФормыКоллекция. Он без проблем «живет» на клиенте, и вы можете обходить его циклом. Для ускорения настройки и создания реквизитов и элементов интерфейса подойдёт модуль программного изменения форм.

Способ 4. Передача через временное хранилище

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

На сервере сформированная таблица значений помещается в хранилище, а на клиент возвращается только короткий строковый адрес:


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

В дальнейшем, когда эти данные снова потребуются для расчетов на сервере, вы передаете этот адрес с клиента обратно на сервер и извлекаете таблицу с помощью функции ПолучитьИзВременногоХранилища(АдресВХранилище).

Важное ограничение типов данных

Какой бы метод вы ни выбрали (ручной массив, БСП или хранилище), обязательно учитывайте одно критическое правило: внутри самих колонок исходной таблицы не должно быть других мутабельных значений!

Все типы данных внутри ячеек (числа, строки, булево, ссылки на справочники или документы, даты) должны поддерживать XDTO-сериализацию. Если в одной из ячеек вашей таблицы случайно окажется объект, который нельзя сериализовать, передача на клиент всё равно завершится ошибкой платформы.

← На главную