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

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

1С: чем заменить таблицу значений на клиенте

Почему таблица значений недоступна на клиенте в 1С и чем её заменить: массив структур, данные формы, вызов сервера. Примеры кода и типичные ошибки.

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

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

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

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

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

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

Вариант 1: массив структур — универсальная замена

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

// Клиентская процедура

&НаКлиенте

Функция СобратьДанныеСтрок()

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

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

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

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

Строка.Цена = 1500;

Результат.Добавить(Строка);

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

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

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

Ограничение массива структур — отсутствие встроенных методов сортировки, свёртки и итогов. Сортировку можно выполнить через СписокЗначений с промежуточной выгрузкой ключей, а итоги — накоплением в цикле. Но если таких операций много, это сигнал, что логику нужно перенести на сервер.

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

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

&НаКлиенте

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

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

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

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

&НаКлиенте

Функция НайтиСтрокуПоКоду(Код)

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

Если Найденные.Количество() > 0 Тогда

Возврат Найденные[0];

КонецЕсли;

Возврат Неопределено;

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

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

Для иерархических данных вместо таблицы используйте реквизит типа «Дерево значений» — на клиенте он представлен как ДанныеФормыДерево с методом ПолучитьЭлементы() для обхода уровней.

Вариант 3: перенос обработки на сервер

Когда нужны именно возможности таблицы значений — свёртка, группировка, сложный поиск, загрузка из запроса — правильное решение не имитировать таблицу на клиенте, а выполнить работу на сервере. Клиент передаёт параметры, сервер возвращает результат в сериализуемом виде.

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

Функция ПолучитьОстатки(Склад)

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

// ... запрос, выгрузка в ТЗ, свертка ...

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

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

Результат.Добавить(Новый Структура("Товар, Остаток", Стр.Товар, Стр.Остаток));

КонецЦикла;

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

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

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

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

Сравнение способов замены

СпособКогда подходитОграничения
Массив структурПередача данных, временные вычисления, возврат из серверных функцийНет сортировки, свёртки и итогов «из коробки»
Реквизит формы (ДанныеФормыТаблица)Отображение и редактирование табличных данных в формеНет методов Свернуть(), Загрузить(); живёт только в форме
СписокЗначенийПростые списки «значение + представление», выбор из спискаТолько одна колонка данных плюс представление и пометка
Серверная процедура с ТЗГруппировки, запросы, большие объёмыЗатраты на серверный вызов; результат нужно сериализовать

Как выбрать замену

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

Данные не показываются пользователю напрямую, нужны только передача и перебор

Реквизит формы

Данные редактируются или отображаются в табличном поле формы

Серверная обработка

Нужны свертка, запрос, группировка или объем больше нескольких сотен строк

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

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

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

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

Типичные ошибки
01
Создание Новый ТаблицаЗначений в клиентской процедуре — ошибка «Тип не определен» в тонком клиенте
02
Возврат ТаблицыЗначений из серверной функции на клиент — ошибка сериализации, преобразуйте в массив структур
03
Использование Вычислить() для обхода ограничения — нестабильно и запрещено в безопасном режиме
04
Перебор массива из тысяч структур на клиенте вместо серверного запроса — заметные задержки интерфейса

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

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

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

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

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

Открытие формы в тонком клиенте
Норма

Форма открывается, таблица заполняется, ошибок нет

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

Ошибка «Тип не определен (ТаблицаЗначений)» или «Ошибка передачи данных»

Проверка конфигурации в конфигураторе
Норма

Нет замечаний по контекстам тонкого и веб-клиента

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

Сообщения о недоступности типа в выбранном контексте

Передача данных с сервера
Норма

Клиент получает массив структур и обрабатывает его

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

Ошибка сериализации при вызове серверной функции

Часто задаваемые вопросы

Можно ли обойти ограничение через Вычислить() или Выполнить()?

Технически выражение Вычислить("Новый ТаблицаЗначений") иногда срабатывает в толстом клиенте, но в тонком и веб-клиенте тип всё равно недоступен, а в безопасном режиме (например, в расширениях и внешних обработках) операторы Вычислить и Выполнить запрещены. Такой обход считается грубой архитектурной ошибкой.

Как отсортировать массив структур на клиенте?

Встроенной сортировки у массива нет. Варианты: перенести данные в реквизит формы и вызвать Сортировать(), использовать СписокЗначений с загрузкой ключей и методом СортироватьПоЗначению(), либо выполнить сортировку на сервере запросом с упорядочиванием.

Чем заменить Свернуть() на клиенте?

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

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

Нет, таблица значений не сериализуется для передачи между контекстами. На сервере преобразуйте её в массив структур или заполните реквизит формы через ЗначениеВРеквизитФормы() в контекстной серверной процедуре формы.

Что использовать для иерархических данных вместо дерева значений?

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

Почему код работает у разработчика, но падает у пользователя?

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

Итог

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

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