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