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

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

Вложенные таблицы в 1С: что это и как с ними работать

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

Вложенные таблицы в 1С — это структуры данных, в которых одна таблица хранится внутри другой: строка «родительской» таблицы содержит целый набор подчинённых строк. Самый распространённый пример — табличная часть документа: у накладной есть шапка (номер, дата, контрагент) и вложенный список товаров с количеством и ценами. Каждая строка товара не существует отдельно от документа — она принадлежит конкретной строке-владельцу.

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

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

Где встречаются вложенные таблицы в 1С

Основное место — табличные части объектов метаданных. Документ «Реализация товаров и услуг» содержит табличную часть «Товары», справочник «Контрагенты» в некоторых конфигурациях — табличную часть с контактными лицами. Физически в базе данных табличная часть хранится в отдельной таблице СУБД, связанной с шапкой по ссылке на объект, но логически она «вложена» в документ.

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

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

Как устроена табличная часть документа

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

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

На форме документа табличная часть отображается как табличное поле, связанное с реквизитом объекта. Пользователь добавляет и редактирует строки интерактивно, а обработчики событий (ПриИзменении, ПриНачалеРедактирования) позволяют пересчитывать суммы, подставлять цены и контролировать ввод.

Как обратиться к вложенной таблице в запросе

В языке запросов 1С табличная часть доступна через точку от имени объекта: Документ.РеализацияТоваровУслуг.Товары. Такой запрос возвращает плоскую таблицу строк, где в каждой строке есть поле «Ссылка» на документ-владелец. Это удобно, когда нужны именно строки: остатки по товарам из документов, анализ цен, поиск строк с конкретной номенклатурой.

Если нужны и шапка, и строки, применяют левое соединение таблицы документа с табличной частью по полю «Ссылка». Альтернатива — обращение к табличной части через поле объекта: РеализацияТоваровУслуг.Товары в списке полей вернёт вложенную таблицу в одной ячейке результата. Такой вариант используют при выгрузке документа целиком, но обходить его сложнее.

bsl
ВЫБРАТЬ
	Реализация.Ссылка КАК Документ,
	Товары.Номенклатура КАК Номенклатура,
	Товары.Количество КАК Количество
ИЗ
	Документ.РеализацияТоваровУслуг КАК Реализация
		ЛЕВОЕ СОЕДИНЕНИЕ Документ.РеализацияТоваровУслуг.Товары КАК Товары
		ПО Реализация.Ссылка = Товары.Ссылка
ГДЕ
	Реализация.Дата МЕЖДУ &НачалоПериода И &КонецПериода

Третий способ — итоги по группировке. Запрос с конструкцией ИТОГИ ПО Ссылка возвращает иерархическую выборку: верхний уровень — документы, вложенный уровень — строки табличной части. В коде это обрабатывается вложенными циклами обхода, что наглядно соответствует структуре «документ → строки».

Обход вложенных таблиц в коде

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

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

Порядок обхода документа с табличной частью
  1. 1
    Получите объект: ДокументОбъект = Ссылка.ПолучитьОбъект()
  2. 2
    Проверьте количество строк: ДокументОбъект.Товары.Количество()
  3. 3
    Обойдите строки циклом Для Каждого СтрокаТовара Из ДокументОбъект.Товары Цикл
  4. 4
    Измените нужные поля строки (цена, количество, сумма)
  5. 5
    Запишите объект: ДокументОбъект.Записать() — иначе изменения пропадут

Для колонки типа «ТаблицаЗначений» внутри таблицы значений логика аналогична: обращаетесь к ячейке строки и получаете объект таблицы, у которого доступны все стандартные методы — Колонки, Строки, Итог, Свернуть. Такой приём применяют при построении деревянных структур для выгрузки в XML или JSON, где вложенность естественна для формата.

Типичные ошибки и ограничения

Частая ошибка новичков — попытка изменить табличную часть через запрос. Запросы в 1С только читают данные; изменить строки можно только через объект документа. Другая распространённая проблема — соединение табличной части без учёта документов с пустыми строками: внутреннее соединение «отсечёт» документы без товаров, поэтому для полного списка шапок используют левое соединение.

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

Типичные ошибки
01
Попытка обновить табличную часть запросом — запросы в 1С не изменяют данные, нужен объект документа
02
Внутреннее соединение с табличной частью — теряются документы без строк, используйте левое соединение
03
Забытый Записать() после изменения строк — все правки теряются без ошибки
04
Обход миллионов строк без отбора по периоду — запрос выполняется минутами и блокирует работу
05
Путаница вложенной таблицы с вложенным запросом — это разные конструкции с разным синтаксисом

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

Когда использовать вложенную таблицу, а когда — отдельный объект

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

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

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

Табличная часть

Строки принадлежат одному владельцу, не нужны отдельные права и отчёты по строкам; простая структура, но нет самостоятельных ссылок

Подчинённый справочник

Элементы привязаны к владельцу, но имеют собственные ссылки, код и могут участвовать в отчётах отдельно

Независимый объект со ссылкой

Сущность живёт отдельно и может относиться к нескольким объектам; максимальная гибкость, но сложнее интерфейс и контроль целостности

Проверка результата и практические приёмы

После написания запроса с соединением табличной части проверьте три вещи: количество строк результата не превышает ожидаемое (декартово произведение при неверном условии связи раздувает выборку), документы без строк присутствуют, если использовали левое соединение, и суммы по строкам сходятся с итогами в шапке документа. Удобный контроль — сравнить СУММА(Товары.Сумма) с реквизитом «СуммаДокумента».

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

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

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

Число строк результата запроса
Норма

Равно сумме строк табличных частей отобранных документов

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

Резко больше — ошибка в условии соединения, дублирование строк

Документы без строк
Норма

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

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

Пропали — использовано внутреннее соединение

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

Значения совпадают

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

Расхождение — часть строк потеряна или задублирована

Выгрузка во внешний формат
Норма

Вложенные строки выгружены массивом внутри документа

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

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

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

Чем вложенная таблица отличается от вложенного запроса?

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

Можно ли изменить табличную часть документа запросом?

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

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

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

Почему запрос с табличной частью возвращает дубли строк?

Чаще всего из-за соединения нескольких табличных частей одного документа без корректных условий связи: каждая строка «Товаров» перемножается на каждую строку «Услуг». Соединяйте табличные части с шапкой по отдельности или объединяйте результаты через ОБЪЕДИНИТЬ ВСЕ, если строки разных частей нужны вместе.

Есть ли ограничение на количество строк в табличной части?

Жёсткого платформенного лимита на практике не достигают, но документы с десятками тысяч строк медленно открываются, проводятся и редактируются. Если строк очень много, стоит пересмотреть архитектуру: разбить документ на несколько или перенести данные в регистр сведений с измерением «документ».

Как найти все документы, где в табличной части есть конкретный товар?

Запросом к табличной части с условием на номенклатуру: выбрать различные значения поля Ссылка из Документ.РеализацияТоваровУслуг.Товары, где Номенклатура = &Товар. Добавьте отбор по периоду и проведённости, чтобы не сканировать всю таблицу.

Итог

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

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