Как правильно обращаться к табличным частям документа в запросах 1С?

Программист 1С v8.3 (Управляемые формы) 1C:Бухгалтерия IT и автоматизация бизнеса
← На главную

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

Почему не стоит использовать вложенные конструкции со скобками?

В тексте запроса синтаксис вида Документ.Товары.(Номенклатура, Количество) технически доступен в языке запросов, но он создает сложную структуру данных, которая неудобна для плоских отчетов. При таком подходе 1С возвращает вложенную выборку для каждой строки, что усложняет формирование печатных форм. Гораздо эффективнее и профессиональнее использовать механизм соединений (LEFT JOIN).

Решение: использование левого соединения

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


ВЫБРАТЬ
    Счет.Номер,
    Счет.Дата,
    СчетТовары.Номенклатура КАК Товар,
    СчетТовары.Количество,
    СчетТовары.Цена,
    СчетТовары.Сумма
ИЗ
    Документ.СчетНаОплатуПокупателю КАК Счет
        ЛЕВОЕ СОЕДИНЕНИЕ Документ.СчетНаОплатуПокупателю.Товары КАК СчетТовары
        ПО Счет.Ссылка = СчетТовары.Ссылка
ГДЕ
    Счет.Ссылка = &ТекущийДокумент

Важные замечания по составлению запроса:

  1. Избегайте запятых в предложении ИЗ, если вы используете оператор ЛЕВОЕ СОЕДИНЕНИЕ. Неправильная пунктуация делает запрос невалидным.
  2. Не пытайтесь соединять две табличные части (например, Товары и Услуги) в одном запросе напрямую. Это приведет к возникновению «декартова произведения», из-за чего данные будут дублироваться, а суммы — искажаться. Лучше сделать два отдельных запроса или использовать объединение ОБЪЕДИНИТЬ ВСЕ.
  3. Для обращения к полям табличной части используйте лаконичные алиасы (псевдонимы), как показано в примере выше (СчетТовары).

Правильный обход результата запроса

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

Разберем эталонный способ обхода:


// Сначала получаем выборку
Результат = Запрос.Выполнить().Выбрать();

// Если нужно сбросить курсор на начало (например, после проверок)
Результат.Сбросить();

// Обходим результат с помощью цикла Пока
Пока Результат.Следующий() Цикл
    // Здесь мы обращаемся к полям текущей строки
    ТекущийТовар = Результат.Товар;
    ТекущееКоличество = Результат.Количество;
    
    // Выводим данные в макет или совершаем другие действия
    ОбластьМакета.Параметры.Товар = ТекущийТовар;
    ТабДокумент.Вывести(ОбластьМакета);
КонецЦикла;

Почему ваш код мог работать некорректно?

Советы по оптимизации

Всегда старайтесь максимально использовать возможности Конструктора запросов. Он автоматически расставляет связи между таблицами, что минимизирует риск ошибок в именах полей или логике соединений. Если вы видите ошибку «Поле объекта не обнаружено», первым делом проверьте, правильно ли указан псевдоним таблицы в ИЗ и соответствует ли он тому, что вы пишете после точки в выражении ВЫБРАТЬ.

Следуя этим правилам, вы сможете писать чистый и производительный код, избегая дублирования строк и потери данных при работе с любыми документами системы 1С.

← На главную