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

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

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

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

Почему возникает ошибка передачи данных?

Давайте проанализируем архитектуру. На тонком клиенте (в управляемой форме) мы работаем не с самой ТаблицаЗначений, а с типом ДанныеФормыКоллекция (реквизит формы). Когда мы пытаемся передать этот объект или созданную программно таблицу на сервер, платформа должна "упаковать" данные. Прямая передача мутабельных (изменяемых) значений сложных типов между клиентом и сервером часто запрещена для оптимизации трафика и целостности данных.

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

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

Это наиболее универсальный и надежный метод. Он подходит для передачи любых объемов данных. Суть метода заключается в том, что мы помещаем данные во временное хранилище (которое доступно и клиенту, и серверу), получаем уникальный адрес, передаем этот адрес строкой на сервер, и там извлекаем данные.

Рассмотрим этот процесс по шагам.

Шаг 1. Помещение данных во временное хранилище на клиенте

Сначала нам нужно получить данные. Если мы работаем с реквизитом формы (например, Объект.Товары), то для помещения в хранилище нам, возможно, потребуется сначала выгрузить их во временную структуру или передать напрямую, если платформа это позволяет для конкретной версии. Однако, наиболее надежный способ — это помещение адреса.

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


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

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

Шаг 2. Получение данных на сервере

Теперь перейдем к серверной части. Здесь мы используем функцию ПолучитьИзВременногоХранилища. Важно понимать, что при извлечении данных формы типа ДанныеФормыКоллекция из хранилища на сервере, они автоматически преобразуются в ТаблицаЗначений.


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

Этот метод хорош тем, что он "родной" для платформы 1С и отлично справляется с большими таблицами, так как механизм временного хранилища оптимизирован для таких операций.

Способ 2: Массив структур (Для небольших объемов)

Если ваша таблица содержит всего несколько строк, использование временного хранилища может показаться избыточным. В таких случаях мы можем преобразовать данные в массив структур. Структуры и массивы легко сериализуются в XDTO и передаются между клиентом и сервером без ошибок.

Разберем, как реализовать этот подход.

На Клиенте:

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


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

На Сервере:

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


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

Сравнение методов и выводы

Давайте подытожим, какой метод выбрать в вашей ситуации:

  1. Временное хранилище (ПоместитьВоВременноеХранилище):

    Используйте этот метод в 90% случаев. Это стандарт, который обеспечивает высокую производительность и читаемость кода. Он идеально подходит, когда нужно передать всю таблицу целиком, особенно если в ней много строк.

  2. Массив структур:

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

Также помните о функции РеквизитФормыВЗначение. Если вы находитесь в модуле формы и вам нужно обработать на сервере текущие данные формы (например, Объект), вам не обязательно передавать их параметром. В серверном контексте формы вы можете конвертировать ДанныеФормыСтруктура в прикладной объект:


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

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

← На главную