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