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

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

Как сделать запрос к табличной части документа 1С

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

Табличная часть документа в 1С хранится в базе данных как отдельная таблица, связанная с шапкой документа по ссылке. Поэтому запрос к табличной части — это обычный запрос на встроенном языке, где в секции «ИЗ» указывается виртуальное имя вида «Документ.РеализацияТоваровУслуг.Товары». Такой подход позволяет выбирать строки, фильтровать их, группировать и соединять с другими таблицами без обхода коллекции в коде.

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

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

Каждая табличная часть документа физически представляет собой отдельную таблицу в базе данных. В ней обязательно присутствует поле «Ссылка» — указатель на документ-владелец, и поле «НомерСтроки» — порядковый номер строки внутри документа. Остальные поля соответствуют реквизитам табличной части, заданным в конфигураторе.

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

Простейший запрос: выборка строк одного документа

Самая частая задача — получить строки табличной части конкретного документа. Для этого достаточно указать таблицу табличной части в секции «ИЗ» и наложить отбор по ссылке. Параметр передаётся через метод «УстановитьПараметр», что защищает от ошибок форматирования и подстановки.

Пример кода выглядит так:

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

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

"ВЫБРАТЬ

| Товары.Номенклатура КАК Номенклатура,

| Товары.Количество КАК Количество,

| Товары.Цена КАК Цена,

| Товары.Сумма КАК Сумма

|ИЗ

| Документ.РеализацияТоваровУслуг.Товары КАК Товары

|ГДЕ

| Товары.Ссылка = &Ссылка

|УПОРЯДОЧИТЬ ПО

| Товары.НомерСтроки";

Запрос.УстановитьПараметр("Ссылка", ДокументСсылка);

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

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

Порядок действий для простого запроса
  1. 1
    Определите точное имя документа и табличной части в конфигураторе
  2. 2
    Составьте текст запроса с таблицей вида Документ.Имя.ТабличнаяЧасть
  3. 3
    Добавьте отбор ГДЕ Ссылка = &Ссылка и передайте параметр
  4. 4
    Добавьте УПОРЯДОЧИТЬ ПО НомерСтроки, если важен порядок строк
  5. 5
    Выполните запрос и проверьте, что количество строк совпадает с документом

Как получить реквизиты шапки вместе со строками табличной части

Часто вместе со строками нужны данные шапки: номер, дата, контрагент, организация. Есть два способа. Первый — обращение к реквизитам шапки «через точку» от поля «Ссылка»: «Товары.Ссылка.Номер», «Товары.Ссылка.Дата». Это коротко, но платформа фактически выполняет неявное соединение, и при больших выборках такой запрос может работать медленнее, чем явное соединение.

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

ВЫБРАТЬ

Реализация.Номер КАК Номер,

Реализация.Дата КАК Дата,

Товары.Номенклатура КАК Номенклатура,

Товары.Сумма КАК Сумма

ИЗ

Документ.РеализацияТоваровУслуг.Товары КАК Товары

ЛЕВОЕ СОЕДИНЕНИЕ Документ.РеализацияТоваровУслуг КАК Реализация

ПО Товары.Ссылка = Реализация.Ссылка

ГДЕ

Реализация.Проведен

Условие «Реализация.Проведен» здесь отсекает непроведённые и помеченные на удаление документы. Без него в отчёт могут попасть черновики, что исказит итоги. Если отбор накладывается на поле соединяемой таблицы, помните: условие в секции «ГДЕ» фактически превращает левое соединение во внутреннее. Если нужно сохранить строки без пары, условие следует переносить в секцию «ПО» соединения.

Два способа получить данные шапки

Обращение через точку (Товары.Ссылка.Номер)

Короткая запись, удобно для одного-двух реквизитов. Минус: скрытое соединение, хуже читаемость и потенциально ниже производительность на больших выборках.

Явное соединение с таблицей документа

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

Отбор по нескольким документам и по периоду

Если нужно выбрать строки табличных частей сразу нескольких документов, передавайте в параметр массив или список значений и используйте оператор «В»:

ГДЕ

Товары.Ссылка В (&СписокДокументов)

Для отбора по периоду корректнее фильтровать по дате документа, а не по данным табличной части — у строк табличной части собственной даты нет. Условие вида «Товары.Ссылка.Дата МЕЖДУ &Начало И &Конец» работает, но на больших объёмах лучше сначала выбрать документы за период во временную таблицу, а затем соединить её с табличной частью. Такой двухшаговый подход сокращает объём обрабатываемых строк и заметно ускоряет выполнение.

Также учитывайте, что граница «Конец» периода должна включать весь последний день. Наиболее надёжный вариант — передать конец дня через функцию «КонецДня» или использовать конструкцию «Дата < &СледующийДень» вместо «МЕЖДУ», чтобы не потерять документы, проведённые в последнюю секунду периода.

Группировка и итоги по строкам табличной части

Табличные части часто агрегируют: суммируют количество и суммы по номенклатуре, считают количество строк. Для этого применяется секция «СГРУППИРОВАТЬ ПО» с агрегатными функциями СУММА, КОЛИЧЕСТВО, МАКСИМУМ:

ВЫБРАТЬ

Товары.Номенклатура КАК Номенклатура,

СУММА(Товары.Количество) КАК Количество,

СУММА(Товары.Сумма) КАК Сумма

ИЗ

Документ.РеализацияТоваровУслуг.Товары КАК Товары

ГДЕ

Товары.Ссылка = &Ссылка

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

Товары.Номенклатура

Если одна и та же номенклатура встречается в документе несколько раз с разными ценами, группировка только по номенклатуре сольёт эти строки в одну. Когда это нежелательно, добавьте цену в список группировки — тогда итоги будут посчитаны по парам «номенклатура + цена».

Для подсчёта уникальных значений используйте «КОЛИЧЕСТВО(РАЗЛИЧНЫЕ Поле)». Обычное «КОЛИЧЕСТВО(Поле)» вернёт число строк, а не число различных позиций — эта подмена является частой причиной расхождений в отчётах.

Когда запрос не нужен: обход табличной части в коде

Не каждая задача требует запроса. Если документ уже открыт в виде объекта (например, в обработчике проведения или при программной обработке одного документа), табличная часть доступна как коллекция и обходится циклом «Для Каждого Строка Из Объект.Товары Цикл». Это проще и не требует обращения к базе данных повторно.

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

Маршрут решения

Как выбрать подход

Нужно обработать строки одного уже открытого объекта документаИспользуйте обход коллекции табличной части в коде без запроса
Нужны данные по многим документам, отчёт или агрегацияСтройте запрос к таблице табличной части с отборами и группировкой
Нужно соединить строки с регистрами или справочникамиИспользуйте запрос с явными соединениями таблиц
Запрос выполняется внутри цикла по документамПерепишите логику: один запрос с отбором по списку документов вместо запроса на каждую итерацию

Типичные ошибки и как их проверить

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

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

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

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

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

Количество строк в выборке
Норма

Совпадает с числом строк табличной части документа

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

Строк больше (дубли от соединения) или меньше (потеря при внутреннем соединении)

Итоговая сумма по запросу
Норма

Равна итогу колонки «Сумма» в документе

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

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

Порядок строк
Норма

Соответствует нумерации в документе при УПОРЯДОЧИТЬ ПО НомерСтроки

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

Строки идут в произвольном порядке — сортировка не задана

Ограничения и особенности платформы

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

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

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

Итог

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

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

Частые вопросы

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

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

Можно ли в одном запросе выбрать данные из двух табличных частей одного документа?

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

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

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

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

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

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

Используйте левое соединение таблицы табличной части с виртуальной таблицей регистра, например «РегистрСведений.ЦеныНоменклатуры.СрезПоследних», по ключевым измерениям (номенклатура, тип цен). Левое соединение сохранит строки документа, даже если цена для позиции не задана — такие строки получат пустое значение цены, что легко обнаружить при проверке.

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

Да, запрос видит строки помеченных документов — пометка удаления не стирает данные. Если такие документы не должны попадать в результат, добавьте условие «НЕ Товары.Ссылка.ПометкаУдаления» или отбор по признаку «Проведен», в зависимости от логики задачи.