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

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

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

Понимание архитектуры: Почему Таблицы значений нет на клиенте

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

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

Способ 1: Использование метода Загрузить (оптимальный вариант)

Если на форме уже создан реквизит (например, с именем ТЗ1), который выведен в виде таблицы, то самым быстрым и эффективным способом будет использование метода Загрузить(). Рассмотрим пример, где мы на сервере формируем таблицу и заполняем её данными о метаданных документов.

Допустим, у нас есть серверная процедура:


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

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

Способ 2: Прямое обращение к реквизиту формы

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


&НаСервере
Процедура ЗаполнитьНапрямую()
    
    // Очищаем старые данные
    ТЗ1.Очистить();
    
    Для каждого ДокМетаданные Из Метаданные.Документы Цикл
        // Добавляем строку непосредственно в реквизит формы
        НоваяСтрока = ТЗ1.Добавить();
        НоваяСтрока.Док = ДокМетаданные.Синоним;
    КонецЦикла;
    
КонецПроцедуры

Важно помнить: ТЗ1 внутри контекстной серверной процедуры (&НаСервере) доступна как объект типа ДанныеФормыКоллекция. Вы можете добавлять и удалять строки, но у вас не будет доступа к методам настоящей таблицы значений, таким как ВыгрузитьКолонку() или Итог().

Способ 3: Использование временного хранилища

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

Рассмотрим правильный алгоритм работы с хранилищем:


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

&НаКлиенте
Процедура ПолучитьДанные()
    
    Адрес = ПоместитьТаблицуВХранилище();
    // Теперь адрес содержит строку вида "e1cib/tempstorage/..."
    // Однако на клиенте мы все равно не сможем преобразовать это в ТЗ!
    // Хранилище полезно только для передачи между серверными вызовами.
    
КонецПроцедуры

Внимание! Даже если вы поместили ТЗ в хранилище, при попытке ПолучитьИзВременногоХранилища на клиенте вы получите ошибку или пустой объект, так как клиент «не знает» типа ТаблицаЗначений. Этот способ подходит только для передачи данных между двумя серверными процедурами.

Способ 4: Массив структур (универсальный способ для клиента)

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


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

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

Разбор типичных ошибок

  1. Ошибка при использовании РеквизитФормыВЗначение: Многие пытаются написать РеквизитФормыВЗначение("Объект") во внешней обработке. Если ваша таблица создана не как часть данных обработки (вкладка "Данные"), а просто как реквизит формы (правая колонка в редакторе формы), то обращаться к ней через "Объект" нельзя. Нужно использовать имя самого реквизита: РеквизитФормыВЗначение("ТЗ1").
  2. Мутабельные значения: Если в вашу серверную таблицу значений попадет объект (например, ДокументОбъект вместо ДокументСсылка), вы не сможете передать её на клиент ни в каком виде. Платформа выдаст ошибку сериализации. Всегда проверяйте, чтобы в колонках были только примитивные типы или ссылки.
  3. Потеря данных при переходе: Помните, что ДанныеФормыКоллекция на клиенте содержит только те данные, которые вы туда явно передали. Если вы добавили колонку в ТЗ на сервере, но не добавили её в реквизиты формы — на клиенте вы её не увидите.

Резюме

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

← На главную