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

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

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

Почему возникает ошибка ЗначениеИзСтрокиВнутр

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

Решение 1: Контекстный серверный вызов и работа с идентификатором строки

Это самый простой и эффективный способ, если ваша задача — заполнить данные в табличной части документа при изменении какого-либо значения (например, при выборе транспортного средства). Вместо того чтобы пытаться «протащить» таблицу значений на клиент, мы передадим на сервер только идентификатор текущей строки и выполним заполнение прямо там.

Проанализируем шаги реализации:

  1. На клиенте в обработчике события ПриИзменении мы получаем идентификатор текущей строки табличной части.
  2. Передаем этот идентификатор в серверную процедуру.
  3. На сервере находим нужную строку в данных формы (через Объект) и заполняем её значениями из полученного среза последних.

Рассмотрим пример кода:


&НаКлиенте
Процедура ТСТСПриИзменении(Элемент)
    // Получаем текущие данные строки
    ТекДанные = Элементы.ТС.ТекущиеДанные;
    Если ТекДанные = Неопределено Тогда
        Возврат;
    КонецЕсли;
    
    // Вызываем серверную процедуру, передавая идентификатор строки
    ТСТСПриИзмененииНаСервере(ТекДанные.ПолучитьИдентификатор());
КонецПроцедуры

&НаСервере
Процедура ТСТСПриИзмененииНаСервере(ИдентификаторСтроки)
    // Находим строку в табличной части объекта по идентификатору
    ТекСтрока = Объект.ТС.НайтиПоИдентификатору(ИдентификаторСтроки);
    Ав = ТекСтрока.ТС;
    
    // Получаем данные из регистра сведений
    Отбор = Новый Структура("Организация, ТС", Объект.Организация, Ав);
    Сведения = РегистрыСведений.уатМестонахождениеТС.СрезПоследних(, Отбор);
    
    Если Сведения.Количество() > 0 Тогда
        // Если имена колонок ТЗ соответствуют именам реквизитов ТЧ,
        // используем быстрый метод заполнения
        ЗаполнитьЗначенияСвойств(ТекСтрока, Сведения[0]);
    КонецЕсли;
КонецПроцедуры

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

Решение 2: Преобразование таблицы значений в массив структур

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

Разберем универсальную функцию для такого преобразования:


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

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

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

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

Проанализируем этот алгоритм:

  1. На сервере вы помещаете таблицу значений во временное хранилище с помощью метода ПоместитьВоВременноеХранилище().
  2. Функция возвращает уникальный адрес (строку), которую вы передаете на клиент.
  3. На клиенте вы храните этот адрес. Когда данные снова понадобятся для обработки на сервере (например, при нажатии кнопки «Ок»), вы передаете этот адрес обратно на сервер и извлекаете таблицу методом ПолучитьИзВременногоХранилища().

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

Решение 4: Загрузка данных в реквизит формы типа «Таблица значений»

Если вам нужно отобразить данные на форме в виде таблицы, создайте реквизит формы с типом ТаблицаЗначений. В платформе 1С 8.3 реквизиты формы этого типа на клиенте представлены как ДанныеФормыКоллекция, что позволяет отображать их в элементе управления «Таблица».

Для быстрой передачи данных из серверной «чистой» ТЗ в реквизит формы используйте метод ЗначениеВДанныеФормы():


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

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

Выводы и рекомендации

Проанализировав все доступные методы, можно выделить следующие правила:

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

← На главную