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

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

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

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

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

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

Посмотрим на ошибочный пример:


&НаСервереБезКонтекста
Функция фПараметрыФирмы(Фирма)
    ТЗ = Фирма.ТабличнаяЧасть1.Выгрузить();
    Возврат ТЗ; // Вызовет ошибку при возврате на клиент
КонецФункции

&НаКлиенте
Процедура ФирмаПриИзменении(Элемент)
    Фирма = Объект.Фирма;
    Если НЕ Фирма.Пустая() Тогда
        ТЗ = фПараметрыФирмы(Фирма); 
        Объект.ТабличнаяЧасть2.Загрузить(ТЗ);
    КонецЕсли;
КонецПроцедуры

Решение 1. Выполнение всей логики на сервере формы (рекомендуемый способ)

Разберем наиболее эффективный подход. Если цель — заполнить реквизит формы документа строками из справочника, передавать сырую таблицу значений на клиент вообще не требуется. Всю операцию чтения и заполнения табличной части формы следует выполнить в контекстной процедуре &НаСервере.

В контексте формы доступен объект Объект (тип ДанныеФормыСтруктура), а его табличная часть представлена коллекцией ДанныеФормыКоллекция, у которой есть метод Загрузить().

Посмотрим на правильный код формы:


&НаСервере
Процедура ЗаполнитьТабличнуюЧастьНаСервере(Фирма)
    ТабЧасть = Фирма.ТабличнаяЧасть1.Выгрузить();
    Объект.ТабличнаяЧасть2.Загрузить(ТабЧасть);
КонецПроцедуры

&НаКлиенте
Процедура ФирмаПриИзменении(Элемент)
    Если ЗначениеЗаполнено(Объект.Фирма) Тогда
        ЗаполнитьТабличнуюЧастьНаСервере(Объект.Фирма);
    КонецЕсли;
КонецПроцедуры

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

Решение 2. Оптимизация получения данных через запрос

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

Для повышения производительности разберем вариант с получением данных через Запрос:


&НаСервере
Процедура ЗаполнитьТабличнуюЧастьЗапросом(Фирма)
    Запрос = Новый Запрос;
    Запрос.Текст = 
        "ВЫБРАТЬ
        |   ТЧ.Номенклатура КАК Номенклатура,
        |   ТЧ.Количество КАК Количество,
        |   ТЧ.Цена КАК Цена
        |ИЗ
        |   Справочник.Фирмы.ТабличнаяЧасть1 КАК ТЧ
        |ГДЕ
        |   ТЧ.Ссылка = &Фирма";
    
    Запрос.УстановитьПараметр("Фирма", Фирма);
    
    ТЗ = Запрос.Выполнить().Выгрузить();
    Объект.ТабличнаяЧасть2.Загрузить(ТЗ);
КонецПроцедуры

Решение 3. Передача табличных данных на клиент через массив структур

Бывают ситуации, когда данные таблицы обязательно нужно передать на тонкий клиент для выполнения интерактивных действий или клиентских проверок без модификации реквизитов формы на сервере. В таком случае данные необходимо преобразовать в типы, доступные на клиенте (Массив и Структура).

Рассмотрим по шагам реализацию передачи структуры данных:

  1. На сервере выгружаем данные и обходим строки таблицы значений.
  2. Для каждой строки формируем Структура с нужными полями и добавляем её в Массив.
  3. Возвращаем массив на тонкий клиент, где он может быть обработан.

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

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

Решение 4. Использование временного хранилища

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

Посмотрим на схему работы:

  1. На сервере помещаем ТаблицаЗначений во временное хранилище и возвращаем на клиент строковый адрес (УникальныйИдентификатор формы обеспечивает автоматическую очистку памяти при закрытии окна).
  2. Клиент оперирует только строкой адреса.
  3. При следующем серверном вызове таблица извлекается через ПолучитьИзВременногоХранилища() обратно на сервере. Непосредственно на клиенте получить таблицу из хранилища нельзя.

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

Итоги

Для решения задачи заполнения табличной части документа из справочника оптимальным решением является выполнение всей операции на сервере в контексте формы (&НаСервере) с использованием метода Объект.ТабличнаяЧасть.Загрузить(). Это сокращает объем передаваемого трафика между клиентом и сервером и предотвращает ошибки недопустимых типов данных.

← На главную