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

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

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

Почему возникает проблема передачи таблицы значений?

Прежде всего, выясним причину такого поведения системы. В управляемом приложении клиентское и серверное приложения работают в разных адресных пространствах. Для взаимодействия между ними используется механизм сериализации — преобразования объекта в поток данных (обычно XML или JSON) для передачи по сети. Объект ТаблицаЗначений предназначен исключительно для работы на стороне сервера (или в толстом клиенте), так как он требует прямого взаимодействия с памятью сервера и может содержать огромные объемы данных, передача которых на клиент была бы неэффективной с точки зрения производительности.

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

Способ №1: Использование массива структур

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

На стороне сервера мы создаем функцию, которая преобразует нашу ТаблицаЗначений в Массив, где каждым элементом будет Структура, ключи которой соответствуют именам колонок таблицы. Рассмотрим пример кода:


&НаСервере
Функция ПолучитьДанныеВМассиве()
    Таблица = Новый ТаблицаЗначений;
    Таблица.Колонки.Добавить("Номенклатура");
    Таблица.Колонки.Добавить("Количество");
    
    // Заполняем таблицу какими-то данными
    НоваяСтрока = Таблица.Добавить();
    НоваяСтрока.Номенклатура = "Товар 1";
    НоваяСтрока.Количество = 10;
    
    МассивРезультат = Новый Массив;
    Для Каждого СтрокаТЗ Из Таблица Цикл
        СтруктураСтроки = Новый Структура;
        Для Каждого Колонка Из Таблица.Колонки Цикл
            СтруктураСтроки.Вставить(Колонка.Имя, СтрокаТЗ[Колонка.Имя]);
        КонецЦикла;
        МассивРезультат.Добавить(СтруктураСтроки);
    КонецЦикла;
    
    Возврат МассивРезультат;
КонецФункции

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

Способ №2: Передача через временное хранилище

Если данных много или нам нужно сохранить объект ТаблицаЗначений "как есть" между вызовами серверных процедур, не нагружая клиент, мы используем ВременноеХранилище. Суть метода заключается в том, что мы помещаем таблицу в специальный кэш на сервере, а на клиент передаем только короткую строку-адрес (УникальныйИдентификатор).

Рассмотрим подробнее реализацию этого алгоритма. Сначала поместим данные в хранилище:


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

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

На клиенте мы сохраняем полученную строку АдресХранилища в переменную. Когда нам снова понадобится эта таблица на сервере, мы просто передаем этот адрес обратно:


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

Способ №3: Работа с реквизитами формы типа "ДанныеФормыКоллекция"

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

Проанализируем ситуацию: на форме есть таблица, связанная с реквизитом Объект.Товары. Чтобы обработать её на сервере как полноценную ТаблицаЗначений (например, для использования в методе Загрузить() или для передачи в запрос), выполним следующие действия:

  1. Преобразуем данные формы в объект ТаблицаЗначений с помощью РеквизитФормыВЗначение("Объект.Товары", Тип("ТаблицаЗначений")).
  2. Проводим необходимые манипуляции (сортировка, поиск, свертка).
  3. Возвращаем измененный объект обратно в структуру формы с помощью ЗначениеВРеквизитФормы(ТЗ, "Объект.Товары").

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

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

Выясним, какой метод выбрать в конкретной ситуации:

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

Таким образом, мы разобрали основные технические подходы к обходу ограничений сериализации. Понимание этих механизмов позволяет строить производительные и отказоустойчивые системы на платформе 1С.

← На главную