К статье
Практический материал

Разработка и Конфигурация · 13 мин

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

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

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

Причина в том, что таблица значений — тяжёлый серверный объект, привязанный к контексту сервера 1С. На клиенте вместо неё используются коллекции, которые умеет сериализовать платформа: массивы, структуры, соответствия и данные формы. Понимание того, как организовать обмен табличными данными между сервером и клиентом, — базовый навык для разработки на управляемых формах.

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

Почему таблица значений недоступна на клиенте

В управляемом приложении код делится на клиентский и серверный. Директивы &НаКлиенте и &НаСервере определяют, где выполняется процедура. Тонкий клиент и веб-клиент физически не имеют доступа к большинству серверных типов: запросам, менеджерам объектов, таблицам значений. Это связано с тем, что клиентская часть платформы — облегчённая среда, которая общается с сервером через сериализованные данные.

Таблица значений хранит описание колонок с типами, индексы и может содержать объекты, не подлежащие передаче через соединение клиент-сервер. Поэтому платформа запрещает её создание в клиентском контексте. Однако есть официальный мост: реквизит формы типа «ТаблицаЗначений» на сервере автоматически преобразуется в ДанныеФормыКоллекция на клиенте, и с ним можно работать почти так же, как с обычной таблицей.

Способ 1: реквизит формы типа «ТаблицаЗначений»

Самый удобный путь — добавить в форму реквизит с типом «ТаблицаЗначений» и описать его колонки. Платформа сама позаботится о передаче данных между клиентом и сервером. На клиенте реквизит доступен как коллекция, строки которой содержат поля по именам колонок.

Порядок настройки: откройте форму в конфигураторе, перейдите на вкладку «Реквизиты», добавьте реквизит, в свойстве «Тип» укажите «ТаблицаЗначений», затем раскройте реквизит и добавьте колонки с нужными типами. Чтобы пользователь видел данные, перетащите реквизит в дерево элементов формы — платформа создаст табличное поле.

&НаКлиенте

Процедура ДобавитьСтроку(Команда)

НоваяСтрока = Товары.Добавить();

НоваяСтрока.Номенклатура = ТекущаяНоменклатура;

НоваяСтрока.Количество = 1;

КонецПроцедуры

&НаКлиенте

Процедура ПосчитатьИтог(Команда)

Итог = 0;

Для Каждого Строка Из Товары Цикл

Итог = Итог + Строка.Сумма;

КонецЦикла;

Сообщить("Итого: " + Итог);

КонецПроцедуры

Обратите внимание: на клиенте у такой коллекции доступны Добавить(), Удалить(), НайтиСтроки(), Итог(), Количество(), обход в цикле. А вот Свернуть(), Скопировать() с отбором и произвольная сортировка требуют серверного вызова.

Способ 2: передача данных с сервера массивом структур

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

&НаСервереБезКонтекста

Функция ПолучитьДанные()

ТЗ = Новый ТаблицаЗначений;

ТЗ.Колонки.Добавить("Код");

ТЗ.Колонки.Добавить("Наименование");

// ... заполнение таблицы ...

Результат = Новый Массив;

Для Каждого СтрокаТЗ Из ТЗ Цикл

Элемент = Новый Структура("Код, Наименование");

ЗаполнитьЗначенияСвойств(Элемент, СтрокаТЗ);

Результат.Добавить(Элемент);

КонецЦикла;

Возврат Результат;

КонецФункции

&НаКлиенте

Процедура ПоказатьДанные(Команда)

Данные = ПолучитьДанные();

Для Каждого Элемент Из Данные Цикл

Сообщить(Элемент.Код + " — " + Элемент.Наименование);

КонецЦикла;

КонецПроцедуры

Ограничение подхода очевидно: структуры не содержат ссылок на изменяемые данные формы, и любая правка на клиенте не вернётся на сервер автоматически — массив нужно передавать обратно явным параметром. Кроме того, ключи структуры должны быть допустимыми идентификаторами, поэтому колонки с пробелами или спецсимволами в именах придётся переименовать.

Способ 3: программное создание таблицы в реквизите формы

Если состав колонок заранее неизвестен и определяется в runtime (например, произвольный отчёт), реквизит создаётся программно через метод ИзменитьРеквизиты(). Это делается только на сервере в контексте формы.

&НаСервере

Процедура СоздатьТаблицуНаФорме()

Добавляемые = Новый Массив;

Добавляемые.Добавить(Новый РеквизитФормы("Период",

Новый ОписаниеТипов("Дата"), "ДинамическаяТаблица"));

Добавляемые.Добавить(Новый РеквизитФормы("Сумма",

Новый ОписаниеТипов("Число"), "ДинамическаяТаблица"));

СначалаТаблица = Новый Массив;

СначалаТаблица.Добавить(Новый РеквизитФормы("ДинамическаяТаблица",

Новый ОписаниеТипов("ТаблицаЗначений")));

ИзменитьРеквизиты(Добавляемые);

КонецПроцедуры

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

Порядок действий для типовой задачи
  1. 1
    Добавьте в форму реквизит типа ТаблицаЗначений и опишите колонки
  2. 2
    Перетащите реквизит в элементы формы для отображения
  3. 3
    В серверной процедуре заполните таблицу через РеквизитФормыВЗначение или напрямую
  4. 4
    На клиенте обходите строки циклом Для Каждого и изменяйте поля
  5. 5
    Для свёртки, сложной сортировки или запроса вызывайте серверную процедуру

Какие операции доступны на клиенте, а какие — только на сервере

Главный источник ошибок — попытка вызвать серверный метод в клиентском коде. Ниже сопоставление возможностей для коллекции формы на клиенте и полноценной таблицы значений на сервере.

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

Практическое правило: всё, что требует массовой обработки, агрегации или обращения к базе данных, выносите на сервер. На клиенте оставляйте интерактив: реакцию на ввод, подсветку, простые итоги, навигацию по строкам.

Сравнение вариантов

Реквизит формы ТаблицаЗначений

Подходит для редактируемых данных, привязанных к форме. Ограничение: часть методов только на сервере, данные живут пока открыта форма.

Массив структур

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

Динамический список

Подходит для отображения данных из базы с фильтрацией. Ограничение: данные только для чтения, источник — запрос к БД, а не произвольная таблица.

Обмен строками между клиентом и сервером

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

Вторая схема — для процедур без контекста формы (&НаСервереБезКонтекста). Туда данные передают параметром в виде массива структур, а на сервере при необходимости загружают в новую таблицу значений через ЗагрузитьКолонку или построчно. Учтите, что ссылки на объекты базы в такой передаче сохраняются, но сама передача больших массивов создаёт накладные расходы.

&НаСервере

Процедура ОбработатьНаСервере()

ТЗ = РеквизитФормыВЗначение("Товары");

ТЗ.Свернуть("Номенклатура", "Количество, Сумма");

ЗначениеВРеквизитФормы(ТЗ, "Товары");

КонецПроцедуры

bsl
ТЗ = РеквизитФормыВЗначение("Товары");
ТЗ.Сортировать("Сумма Убыв");
ЗначениеВРеквизитФормы(ТЗ, "Товары");

Типичные ошибки и как их избежать

Самая частая ошибка — попытка написать Новый ТаблицаЗначений в клиентской процедуре. Компилятор модуля формы либо сразу сообщит о недопустимости, либо код упадёт при выполнении. Решение — перенести создание таблицы в серверную процедуру или использовать реквизит формы.

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

Третья типичная проблема — потеря типов при передаче через структуры. Если в колонке таблицы был составной тип или значение неопределённого типа, после копирования в структуру и обратно тип может «сузиться». Проверяйте критичные поля после обратного преобразования.

Типичные ошибки
01
Создание ТаблицаЗначений в клиентском коде — компиляция падает или выполнение прерывается; создавайте таблицу только на сервере
02
Серверный вызов внутри цикла по строкам — сотни сетевых обращений и зависание формы; выносите обработку в один серверный вызов
03
Ожидание, что изменения массива структур сами вернутся на сервер — данные теряются; передавайте массив обратно явно
04
Использование имён колонок с пробелами при передаче в структуру — ошибка создания ключа; переименуйте колонки в допустимые идентификаторы

Проверка результата и отладка

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

Для отладки удобно временно выводить содержимое коллекции через Сообщить() в цикле или использовать окно «Вычислить выражение» в конфигураторе при остановке в точке останова — там можно раскрыть коллекцию формы и посмотреть значения каждой строки.

Контрольные точки

Как проверить результат

Количество строк на клиенте и сервере
Норма

Значения совпадают до и после обработки

Тревожный признак

Строки пропали или задвоились после вызова сервера

Типы в ссылочных колонках
Норма

Поля содержат ссылки на объекты базы

Тревожный признак

Вместо ссылок строки с представлением — поиск и отборы перестанут работать

Скорость работы формы
Норма

Один серверный вызов на операцию, форма отзывчива

Тревожный признак

Задержка растёт пропорционально числу строк — вызовы идут в цикле

Итог

Что важно запомнить

Таблица значений на клиенте напрямую недоступна. Используйте реквизит формы типа ТаблицаЗначений для редактируемых данных или массив структур для разовой передачи. Массовую обработку — свёртку, сортировку, запросы — выполняйте на сервере одним вызовом, а на клиенте оставляйте только интерактив.

Частые вопросы

Можно ли создать таблицу значений в толстом клиенте?

Да. В толстом клиенте обычного приложения объект ТаблицаЗначений доступен и на клиенте, поскольку там нет жёсткого разделения контекстов. Ограничение касается тонкого клиента, веб-клиента и управляемых форм. Если конфигурация работает только в режиме обычного приложения, старый код с таблицами на клиенте продолжит функционировать.

Как отсортировать таблицу на клиенте без серверного вызова?

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

Что делать, если таблица большая и форма тормозит?

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

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

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

Чем массив структур хуже таблицы значений?

У массива структур нет встроенных методов поиска по отбору, свёртки, итогов и сортировки — всё это придётся писать вручную циклами. Также структура требует, чтобы ключи были допустимыми идентификаторами, и не хранит описание типов колонок. Зато массив легче по памяти и свободно передаётся между клиентом и сервером.

Можно ли использовать таблицу значений в мобильном клиенте?

Ограничения те же, что и для тонкого клиента: объект ТаблицаЗначений доступен только на сервере. На мобильном клиенте работайте через реквизиты формы и коллекции формы. Дополнительно учитывайте, что мобильная платформа чувствительнее к объёму передаваемых данных, поэтому минимизируйте состав колонок.