Разработка и Конфигурация · 11 мин
1С: чем заменить таблицу значений на клиенте
Почему таблица значений недоступна на клиенте в 1С и чем её заменить: массив структур, данные формы, вызов сервера. Примеры кода и типичные ошибки.
Разработчик, привыкший к толстому клиенту или серверному коду, часто сталкивается с ошибкой «Тип не определен (ТаблицаЗначений)» при попытке создать таблицу значений в клиентской процедуре управляемой формы. Это не сбой платформы, а осознанное ограничение: в тонком и веб-клиенте объект ТаблицаЗначений недоступен, потому что он требует значительных ресурсов и не сериализуется для передачи между клиентом и сервером.
Платформа 1С:Предприятие 8 в режиме управляемого приложения жёстко разделяет контексты исполнения. На клиенте доступны лишь «лёгкие» типы: примитивы, Массив, Структура, Соответствие, СписокЗначений, а также данные формы. Таблица значений существует только на сервере, и любая попытка обойти это через Вычислить() или хитрые приёмы приведёт к нестабильной работе.
Хорошая новость в том, что практически любую задачу, которую решают через таблицу значений, можно реализовать на клиенте другими средствами — часто даже эффективнее. Ниже разобраны все рабочие варианты замены с примерами кода, условиями выбора и типичными ошибками.
Почему таблица значений недоступна на клиенте
Таблица значений — это полноценный объект с индексами, итогами, произвольными типами колонок и методами выгрузки. Передача такого объекта между клиентом и сервером требует сериализации всей структуры, что при больших объёмах данных создаёт заметную нагрузку на сеть и память клиентского приложения.
Поэтому в управляемых формах таблица значений существует в двух ипостасях: на сервере — как привычный объект ТаблицаЗначений, на клиенте — только в виде данных формы (ДанныеФормыТаблица или ДанныеФормыДерево), если таблица добавлена как реквизит формы. Создать «свободную» таблицу значений через Новый ТаблицаЗначений в клиентском контексте нельзя.
Вариант 1: массив структур — универсальная замена
Самый распространённый способ заменить таблицу значений на клиенте — массив, элементами которого являются структуры. Каждая структура играет роль строки, а её ключи — роль колонок. Такая конструкция полностью доступна на клиенте, сериализуется и передаётся в серверные вызовы без ограничений.
// Клиентская процедура
&НаКлиенте
Функция СобратьДанныеСтрок()
Результат = Новый Массив;
Строка = Новый Структура("Номенклатура, Количество, Цена");
Строка.Номенклатура = ТекНоменклатура;
Строка.Количество = 2;
Строка.Цена = 1500;
Результат.Добавить(Строка);
Возврат Результат;
КонецФункции
Для поиска в массиве структур применяется обычный перебор циклом. Если записей немного (десятки или сотни), это работает мгновенно. При тысячах записей стоит пересмотреть архитектуру: возможно, поиск должен выполняться на сервере запросом.
Ограничение массива структур — отсутствие встроенных методов сортировки, свёртки и итогов. Сортировку можно выполнить через СписокЗначений с промежуточной выгрузкой ключей, а итоги — накоплением в цикле. Но если таких операций много, это сигнал, что логику нужно перенести на сервер.
Вариант 2: реквизит формы типа «ТаблицаЗначений»
Если данные нужно показать пользователю или дать ему возможность редактирования, правильный путь — добавить в форму реквизит с типом «Таблица значений» и вывести его на форму табличным полем. На клиенте вы будете работать с ним как с коллекцией ДанныеФормыТаблица.
&НаКлиенте
Процедура ДобавитьСтроку(Команда)
НоваяСтрока = Товары.Добавить();
НоваяСтрока.Количество = 1;
КонецПроцедуры
&НаКлиенте
Функция НайтиСтрокуПоКоду(Код)
Найденные = Товары.НайтиСтроки(Новый Структура("Код", Код));
Если Найденные.Количество() > 0 Тогда
Возврат Найденные[0];
КонецЕсли;
Возврат Неопределено;
КонецФункции
Такой реквизит поддерживает на клиенте методы Добавить(), Удалить(), НайтиСтроки(), Итог(), Сортировать(), Очистить(), индексацию и перебор. Для большинства интерфейсных задач этого достаточно. Недоступны лишь серверные методы: Свернуть(), Загрузить(), Скопировать() и работа с индексами.
Для иерархических данных вместо таблицы используйте реквизит типа «Дерево значений» — на клиенте он представлен как ДанныеФормыДерево с методом ПолучитьЭлементы() для обхода уровней.
Вариант 3: перенос обработки на сервер
Когда нужны именно возможности таблицы значений — свёртка, группировка, сложный поиск, загрузка из запроса — правильное решение не имитировать таблицу на клиенте, а выполнить работу на сервере. Клиент передаёт параметры, сервер возвращает результат в сериализуемом виде.
&НаСервереБезКонтекста
Функция ПолучитьОстатки(Склад)
ТЗ = Новый ТаблицаЗначений;
// ... запрос, выгрузка в ТЗ, свертка ...
Результат = Новый Массив;
Для Каждого Стр Из ТЗ Цикл
Результат.Добавить(Новый Структура("Товар, Остаток", Стр.Товар, Стр.Остаток));
КонецЦикла;
Возврат Результат;
КонецФункции
Альтернатива — заполнить серверную процедуру в контексте формы (&НаСервере), где реквизит формы можно преобразовать в таблицу значений через РеквизитФормыВЗначение("Товары"), обработать и вернуть обратно через ЗначениеВРеквизитФормы(). Это стандартный приём для пересчёта итогов, группировок и загрузки данных в табличную часть формы.
- 1Определите, какие операции требуют таблицы значений: свертка, запрос, сложная фильтрация
- 2Создайте серверную процедуру или функцию с директивой &НаСервере или &НаСервереБезКонтекста
- 3Передайте на сервер только необходимые параметры, а не всю коллекцию целиком
- 4Верните результат как массив структур или заполните реквизит формы через ЗначениеВРеквизитФормы
- 5Проверьте работу в тонком клиенте: убедитесь, что нет обращений к недоступным типам
Сравнение способов замены
| Способ | Когда подходит | Ограничения |
|---|---|---|
| Массив структур | Передача данных, временные вычисления, возврат из серверных функций | Нет сортировки, свёртки и итогов «из коробки» |
| Реквизит формы (ДанныеФормыТаблица) | Отображение и редактирование табличных данных в форме | Нет методов Свернуть(), Загрузить(); живёт только в форме |
| СписокЗначений | Простые списки «значение + представление», выбор из списка | Только одна колонка данных плюс представление и пометка |
| Серверная процедура с ТЗ | Группировки, запросы, большие объёмы | Затраты на серверный вызов; результат нужно сериализовать |
Как выбрать замену
Данные не показываются пользователю напрямую, нужны только передача и перебор
Данные редактируются или отображаются в табличном поле формы
Нужны свертка, запрос, группировка или объем больше нескольких сотен строк
Типичные ошибки и как их избежать
Самая частая ошибка — попытка создать таблицу значений в клиентском модуле или в директиве &НаКлиенте. Компилятор формы не всегда останавливает такой код при сохранении, и ошибка всплывает только в рантайме у пользователя. Проверяйте директивы компиляции и прогоняйте форму в тонком клиенте до передачи в работу.
Вторая ошибка — передача таблицы значений как параметра или результата серверного вызова. Платформа выдаст ошибку сериализации. Решение — преобразование в массив структур на сервере перед возвратом, как показано в примере выше.
Третья ошибка — эмуляция таблицы значений через Соответствие или вложенные структуры там, где достаточно реквизита формы. Такой код трудно читать и поддерживать, а пользователь лишается нормального табличного интерфейса.
Проверка результата
После рефакторинга убедитесь, что форма открывается и работает в тонком клиенте и, если используется, в веб-клиенте — именно там ограничения максимальны. Толстый клиент может «проглотить» код, который упадёт у реальных пользователей.
Полезно включить в конфигураторе проверку модулей с указанием контекстов: «Тонкий клиент», «Веб-клиент», «Сервер». Проверка покажет обращения к недоступным типам ещё на этапе разработки. Для этого в меню «Конфигурация» выберите «Проверка конфигурации» и отметьте нужные режимы.
Как проверить результат
Форма открывается, таблица заполняется, ошибок нет
Ошибка «Тип не определен (ТаблицаЗначений)» или «Ошибка передачи данных»
Нет замечаний по контекстам тонкого и веб-клиента
Сообщения о недоступности типа в выбранном контексте
Клиент получает массив структур и обрабатывает его
Ошибка сериализации при вызове серверной функции
Часто задаваемые вопросы
Можно ли обойти ограничение через Вычислить() или Выполнить()?
Технически выражение Вычислить("Новый ТаблицаЗначений") иногда срабатывает в толстом клиенте, но в тонком и веб-клиенте тип всё равно недоступен, а в безопасном режиме (например, в расширениях и внешних обработках) операторы Вычислить и Выполнить запрещены. Такой обход считается грубой архитектурной ошибкой.
Как отсортировать массив структур на клиенте?
Встроенной сортировки у массива нет. Варианты: перенести данные в реквизит формы и вызвать Сортировать(), использовать СписокЗначений с загрузкой ключей и методом СортироватьПоЗначению(), либо выполнить сортировку на сервере запросом с упорядочиванием.
Чем заменить Свернуть() на клиенте?
Напрямую — ничем, метода свёртки в клиентских коллекциях нет. Практичные пути: накопление итогов в соответствии при переборе массива структур (ключ — группировочное поле, значение — сумма) или вызов серверной функции, где доступна полноценная таблица значений с методом Свернуть().
Можно ли вернуть таблицу значений из серверной функции на клиент?
Нет, таблица значений не сериализуется для передачи между контекстами. На сервере преобразуйте её в массив структур или заполните реквизит формы через ЗначениеВРеквизитФормы() в контекстной серверной процедуре формы.
Что использовать для иерархических данных вместо дерева значений?
Добавьте в форму реквизит типа «Дерево значений» — на клиенте он доступен как ДанныеФормыДерево с обходом через ПолучитьЭлементы(). Если отображение не требуется, используйте массив структур, где каждая структура содержит вложенный массив дочерних элементов.
Почему код работает у разработчика, но падает у пользователя?
Чаще всего разработчик тестирует в толстом клиенте, где таблица значений доступна, а пользователи работают в тонком или веб-клиенте. Всегда проверяйте формы в тонком клиенте и включайте проверку конфигурации по всем используемым контекстам исполнения.
Что важно запомнить
Таблица значений на клиенте недоступна по архитектурным причинам, и обходить это не нужно. Для передачи данных используйте массив структур, для отображения — реквизит формы типа «ТаблицаЗначений», а свёртку, группировку и работу с большими объёмами выполняйте на сервере с возвратом сериализуемого результата.