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

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

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

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

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

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

Ниже разобраны все основные сценарии с примерами кода, ограничениями и типичными ошибками. Примеры применимы к платформе 8.3 и управляемым формам, где не указано иное.

Создание таблицы значений программно

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

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

Таблица.Колонки.Добавить("Номенклатура", Новый ОписаниеТипов("СправочникСсылка.Номенклатура"));

Таблица.Колонки.Добавить("Количество", Новый ОписаниеТипов("Число", Новый КвалификаторыЧисла(15, 3)));

Таблица.Колонки.Добавить("Цена", Новый ОписаниеТипов("Число", Новый КвалификаторыЧисла(15, 2)));

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

НоваяСтрока.Номенклатура = Справочники.Номенклатура.НайтиПоКоду("000000001");

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

НоваяСтрока.Цена = 1200;

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

Для подсчёта итогов по колонке используется метод Таблица.Итог("Цена"), для поиска строк — Найти() и НайтиСтроки() с структурой отбора. Эти методы работают только в памяти и не обращаются к базе данных.

Получение таблицы значений из запроса

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

Запрос = Новый Запрос;

Запрос.Текст =

"ВЫБРАТЬ

| Продажи.Номенклатура КАК Номенклатура,

| СУММА(Продажи.Количество) КАК Количество

|ИЗ

| РегистрНакопления.Продажи.Обороты(&НачалоПериода, &КонецПериода, , ) КАК Продажи

|СГРУППИРОВАТЬ ПО

| Продажи.Номенклатура";

Запрос.УстановитьПараметр("НачалоПериода", НачалоМесяца(ТекущаяДатаСеанса()));

Запрос.УстановитьПараметр("КонецПериода", КонецМесяца(ТекущаяДатаСеанса()));

Таблица = Запрос.Выполнить().Выгрузить();

Метод Выгрузить() без параметров возвращает именно таблицу значений. Если передать в него значение ОбходРезультатаЗапроса.ПоГруппировкам, результатом будет дерево значений — это другой объект с иерархией строк, и методы у него отличаются.

Выгрузка только нужных колонок

Если из результата запроса нужны не все поля, их можно перечислить вторым параметром: Выгрузить(ОбходРезультатаЗапроса.Прямой, "Номенклатура,Количество"). Это уменьшает объём памяти, но при обращении к невыгруженной колонке возникнет ошибка, поэтому перечисляйте поля осознанно.

Выгрузка из табличной части документа или справочника

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

ДокументОбъект = ДокументСсылка.ПолучитьОбъект();

ТаблицаТовары = ДокументОбъект.Товары.Выгрузить();

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

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

Выгрузка без открытия объекта

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

Получение таблицы значений на форме

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

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

&НаСервере

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

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

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

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

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

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

Если таблица на форме большая, каждый вызов РеквизитФормыВЗначение копирует её целиком. При обработке в цикле вынесите преобразование за пределы цикла: получите объект один раз, обработайте, верните один раз.
ПЗ
Практическое замечание

Сравнение способов получения таблицы значений

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

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

Как выбрать действие

Данные нужно отобрать из базы с условиями и группировкойИспользуйте запрос с методом Выгрузить()
Нужно изменить строки табличной части документаПолучите объект, выгрузите табличную часть, обработайте, загрузите обратно и запишите
Таблица собирается из внешнего файла или расчётаСоздайте Новый ТаблицаЗначений с явным описанием типов колонок
Нужно обработать таблицу на управляемой формеВ серверной процедуре преобразуйте реквизит через РеквизитФормыВЗначение

Проверка результата и типичные ошибки

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

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

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

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

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

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

Совпадает с ожидаемым числом записей по отбору

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

Ноль строк при заведомо существующих данных — проверьте параметры запроса

Состав колонок
Норма

Все нужные поля присутствуют, типы соответствуют данным

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

Колонка отсутствует или содержит строки вместо чисел

Данные после загрузки обратно в объект
Норма

Табличная часть документа совпадает с обработанной таблицей

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

Часть строк пропала — выгружалась неполная таблица

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

Чем таблица значений отличается от дерева значений?

Таблица значений — плоская структура: строки одного уровня. Дерево значений хранит иерархию: у строк есть родители и подчинённые строки. Дерево получают из запроса с группировками через Выгрузить(ОбходРезультатаЗапроса.ПоГруппировкам) и используют для иерархических данных вроде групп номенклатуры.

Можно ли получить таблицу значений без запроса, если данные в базе?

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

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

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

Почему метод Выгрузить() у запроса возвращает не таблицу, а дерево?

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

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

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

Есть ли ограничение на размер таблицы значений?

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

Итог

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

Основной способ получить таблицу значений из базы — Запрос.Выполнить().Выгрузить(). Из табличной части объекта — метод Выгрузить() с последующей Загрузить() при изменениях. Для ручного формирования — Новый ТаблицаЗначений с явными типами колонок. В управляемых формах обработку выполняйте на сервере через РеквизитФормыВЗначение.