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

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

Как выбрать табличную часть из документа в 1С 8

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

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

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

Ниже разобраны все рабочие способы с примерами кода, условиями их применения и ограничениями. Примеры ориентированы на встроенный язык запросов 1С 8.2/8.3, который одинаково работает и в обычном, и в управляемом приложении.

Как устроено хранение табличных частей в базе 1С

Каждая табличная часть документа физически является отдельной таблицей. В ней хранятся реквизиты строк (номенклатура, количество, цена и т.д.), служебное поле номера строки НомерСтроки и поле Ссылка, указывающее на документ-владелец. Именно через это поле строки привязываются к шапке.

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

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

Базовый сценарий — получить строки табличной части конкретного документа, ссылка на который уже известна. Запрос выглядит так:

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

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

"ВЫБРАТЬ

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

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

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

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

|ИЗ

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

|ГДЕ

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

|

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

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

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

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

Обратите внимание на три момента. Во-первых, псевдоним таблицы (КАК Товары) делает текст читаемым и обязателен при соединениях. Во-вторых, сортировка по НомерСтроки восстанавливает порядок строк, который пользователь видит в форме, — без неё порядок не гарантирован. В-третьих, ссылка всегда передаётся параметром, а не конкатенацией строки: это защищает от ошибок и ускоряет выполнение.

Если нужны все колонки, допустимо написать ВЫБРАТЬ *, но в прикладном коде лучше перечислять поля явно — так запрос устойчивее к изменениям конфигурации и быстрее выполняется.

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

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

Чаще всего строки нужны в контексте документа: с датой, номером, контрагентом, складом. Для этого табличную часть соединяют с основной таблицей документа по полю Ссылка:

ВЫБРАТЬ

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

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

Реализация.Контрагент КАК Контрагент,

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

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

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

ИЗ

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

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

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

ГДЕ

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

И Реализация.Дата МЕЖДУ &НачалоПериода И &КонецПериода

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

Альтернатива соединению — обращение через точку от поля ссылки: Товары.Ссылка.Дата, Товары.Ссылка.Контрагент. Запрос получается короче, но платформа внутри всё равно выполняет соединение, а при обращении через точку к нескольким полям могут строиться избыточные соединения. Для одного-двух полей шапки это приемлемо, для массовых выборок предпочтительнее явное соединение.

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

Соединение по Ссылка

Подходит для выборок по многим документам и нескольким полям шапки. Требует аккуратного указания псевдонимов, но предсказуемо по производительности.

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

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

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

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

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

"ВЫБРАТЬ

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

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

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

|ИЗ

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

|ГДЕ

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

|

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

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

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

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

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

Если документов много и список формируется другим запросом, эффективнее использовать соединение с шапкой и условия по её реквизитам вместо передачи громоздкого списка ссылок.

Обход результата: выборка, таблица значений и группировки

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

Выборка = Запрос.Выполнить().Выбрать();

Пока Выборка.Следующий() Цикл

Сообщить(Строка(Выборка.Номенклатура) + ": " + Выборка.Количество);

КонецЦикла;

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

Перед обходом полезно проверять Результат.Пустой() — это явный признак того, что условия ничего не нашли, и позволяет корректно сообщить об этом пользователю вместо молчаливого пропуска логики.

Порядок действий для выборки табличной части
  1. 1
    Определите точное имя документа и табличной части в конфигураторе
  2. 2
    Составьте запрос к Документ.Имя.ТабличнаяЧасть с псевдонимом таблицы
  3. 3
    Добавьте условие по Ссылка (одна ссылка или список через В) либо соединение с шапкой
  4. 4
    Передайте параметры через УстановитьПараметр, не вставляйте значения в текст
  5. 5
    Выполните запрос и проверьте Пустой() до обхода результата
  6. 6
    Обойдите выборку или выгрузите таблицу значений с сортировкой по НомерСтроки

Альтернатива запросу: обращение к табличной части через объект

Если документ уже открыт как объект (например, в обработчике проведения или после ПолучитьОбъект()), запрос не нужен вовсе — табличная часть доступна как коллекция:

Для Каждого СтрокаТовара Из ДокументОбъект.Товары Цикл

// СтрокаТовара.Номенклатура, СтрокаТовара.Количество и т.д.

КонецЦикла;

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

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

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

Самая частая ошибка — попытка выбрать реквизит табличной части из основной таблицы документа: ВЫБРАТЬ Товары.Номенклатура ИЗ Документ.РеализацияТоваровУслуг. Конструктор запросов подчеркнёт такое поле как недопустимое, потому что в шапке его физически нет. Лечится указанием полного пути к табличной части в секции ИЗ.

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

Для проверки корректности сопоставьте итоги запроса с данными формы документа: сумма по колонке в выборке должна совпадать с итогом табличной части на экране. Расхождение почти всегда означает лишние документы в выборке или дублирование строк из-за соединения.

Типичные ошибки
01
Выбор реквизитов табличной части из основной таблицы документа — запрос не выполнится, поле нужно брать из Документ.Имя.ТабличнаяЧасть
02
Отсутствие фильтра по Проведен — в результат попадают строки непроведённых и помеченных документов
03
Соединение двух табличных частей одного документа без условия связи — строки перемножаются, суммы завышаются
04
Подстановка ссылки в текст запроса строкой вместо параметра — ошибки выполнения и риск некорректной работы
05
Забытая сортировка по НомерСтроки — порядок строк в выборке не совпадает с формой документа
Контрольные точки

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

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

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

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

Строк больше — вероятно, нет фильтра по ссылке или лишнее соединение

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

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

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

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

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

Только проведённые документы за нужный период

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

Присутствуют помеченные на удаление — добавьте условие Проведен

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

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

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

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

Нет, запрос обращается к конкретному виду документа. Для сбора строк из разных видов (например, реализации и возвраты) пишут объединение нескольких запросов через ОБЪЕДИНИТЬ ВСЕ с приведением полей к общему составу.

Чем отличается Выгрузить() от Выбрать()?

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

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

Поле НомерСтроки доступно в табличной части напрямую: ВЫБРАТЬ Т.НомерСтроки ИЗ Документ.Имя.ТабличнаяЧасть КАК Т. Оно соответствует номеру, который пользователь видит в первой колонке таблицы в форме документа.

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

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

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

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

Итог

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

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