Как вывести в печатную форму подчиненного документа данные табличной части из документа-основания в 1С?

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

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

Штатный конструктор печати платформы 1С умеет оперировать только реквизитами и собственными табличными частями того объекта конфигурации, для которого генерируется макет. Получение строк из документа-основания всегда требует ручной доработки текста запроса и процедур вывода в табличный документ.

Типичные ошибки при обращении к табличной части основания

Проанализируем частые ошибки, возникающие при попытке получить строки табличной части документа-основания:

  1. Попытка разыменования табличной части через точку: Конструкция вида Заявка.ДокументОснование.Товары в языке запросов 1С является синтаксически неверной. Табличные части не хранятся внутри ссылки объекта — они представляют собой отдельные физические таблицы базы данных.
  2. Обращение к реквизиту в секции ИЗ: Нельзя писать ИЗ Документ.ДокументОснование. В секции источников данных указываются только реальные имена объектов метаданных конфигурации, например Документ.ЗаявкаНаДоставку или Документ.РеализацияТоваровУслуг.Товары.
  3. Использование составного типа без приведения: Если реквизит ДокументОснование имеет составной тип данных, прямое соединение может привести к неоптимальному плану выполнения или ошибкам. В таких ситуациях обязательно применяется конструкция ВЫРАЗИТЬ().
  4. Ошибки в коде обхода: Попытки вызова несуществующих методов (например, ПолучитьДокумент()) или несоответствие переменных запроса и выборки приводят к аварийному завершению выполнения процедуры.

Способ 1. Запрос с левым соединением к табличной части основания

Разберем классический вариант построения запроса, в котором к таблице шапки текущего документа присоединяется табличная часть документа-основания. Выясним, как правильно связать таблицы по ссылке основания и выполнить обход с помощью группировок.

Посмотрим на пример текста запроса и процедуры вывода:


Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ
    |	Заявка.Ссылка КАК Ссылка,
    |	Заявка.Номер КАК Номер,
    |	Заявка.Дата КАК Дата,
    |	Заявка.ДокументОснование КАК ДокументОснование,
    |	ТоварыРеализации.НомерСтроки КАК НомерСтроки,
    |	ТоварыРеализации.Номенклатура КАК Номенклатура,
    |	ТоварыРеализации.Количество КАК Количество,
    |	ТоварыРеализации.Цена КАК Цена,
    |	ТоварыРеализации.Сумма КАК Сумма
    |ИЗ
    |	Документ.ЗаявкаНаДоставку КАК Заявка
    |	ЛЕВОЕ СОЕДИНЕНИЕ Документ.РеализацияТоваровУслуг.Товары КАК ТоварыРеализации
    |		ПО Заявка.ДокументОснование = ТоварыРеализации.Ссылка
    |ГДЕ
    |	Заявка.Ссылка В (&МассивСсылок)
    |ИТОГИ ПО
    |	Ссылка";

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

ОбластьШапка = Макет.ПолучитьОбласть("Шапка");
ОбластьТоварыШапка = Макет.ПолучитьОбласть("ТоварыШапка");
ОбластьТовары = Макет.ПолучитьОбласть("Товары");
ОбластьПодвал = Макет.ПолучитьОбласть("Подвал");

ВыборкаДокумент = РезультатЗапроса.Выбрать(ОбходРезультатаЗапроса.ПоГруппировкам);

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

Способ 2. Использование пакетного запроса

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

Разберем по шагам логику работы пакета:

  1. В первом запросе пакета выбираются данные шапки документа ЗаявкаНаДоставку и помещаются во временную таблицу.
  2. Во втором запросе данные табличной части РеализацияТоваровУслуг.Товары выбираются напрямую с отбором по ссылке из временной таблицы.
  3. Результаты пакета обрабатываются методом ВыполнитьПакет(), возвращая отдельные выборки для шапки и строк.

Посмотрим на пример реализации пакетного запроса:


Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ
    |	Заявка.Ссылка КАК Ссылка,
    |	Заявка.Номер КАК Номер,
    |	Заявка.Дата КАК Дата,
    |	Заявка.ДокументОснование КАК ДокументОснование
    |ПОМЕСТИТЬ ВТ_Заявки
    |ИЗ
    |	Документ.ЗаявкаНаДоставку КАК Заявка
    |ГДЕ
    |	Заявка.Ссылка В (&МассивСсылок)
    |;
    |
    |////////////////////////////////////////////////////////////////////////////////
    |ВЫБРАТЬ
    |	ВТ_Заявки.Ссылка КАК Ссылка,
    |	ВТ_Заявки.Номер КАК Номер,
    |	ВТ_Заявки.Дата КАК Дата,
    |	ВТ_Заявки.ДокументОснование КАК ДокументОснование
    |ИЗ
    |	ВТ_Заявки КАК ВТ_Заявки
    |;
    |
    |////////////////////////////////////////////////////////////////////////////////
    |ВЫБРАТЬ
    |	Товары.Ссылка КАК ДокументОснование,
    |	Товары.НомерСтроки КАК НомерСтроки,
    |	Товары.Номенклатура КАК Номенклатура,
    |	Товары.Количество КАК Количество,
    |	Товары.Цена КАК Цена,
    |	Товары.Сумма КАК Сумма
    |ИЗ
    |	Документ.РеализацияТоваровУслуг.Товары КАК Товары
    |ГДЕ
    |	Товары.Ссылка В
    |		(ВЫБРАТЬ
    |			ВТ_Заявки.ДокументОснование
    |		ИЗ
    |			ВТ_Заявки КАК ВТ_Заявки)";

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

ВыборкаШапка = МассивРезультатов[1].Выбрать();
ТаблицаТовары = МассивРезультатов[2].Выгрузить();

Пока ВыборкаШапка.Следующий() Цикл
    
    ОбластьШапка = Макет.ПолучитьОбласть("Шапка");
    ОбластьШапка.Параметры.Заполнить(ВыборкаШапка);
    ТабДок.Вывести(ОбластьШапка);
    
    ТабДок.Вывести(Макет.ПолучитьОбласть("ТоварыШапка"));
    ОбластьСтроки = Макет.ПолучитьОбласть("Товары");
    
    Отбор = Новый Структура("ДокументОснование", ВыборкаШапка.ДокументОснование);
    НайденныеСтроки = ТаблицаТовары.НайтиСтроки(Отбор);
    
    Для Каждого СтрокаТЧ Из НайденныеСтроки Цикл
        ОбластьСтроки.Параметры.Заполнить(СтрокаТЧ);
        ТабДок.Вывести(ОбластьСтроки);
    КонецЦикла;
    
    ТабДок.Вывести(Макет.ПолучитьОбласть("Подвал"));
    
КонецЦикла;

Важные практические рекомендации

При реализации вывода данных из связанных документов обязательно учитывайте следующие моменты:

  1. Проверка заполненности основания: Если заявка была введена вручную без указания документа-основания, реквизит ДокументОснование будет пустой ссылкой. В коде формирования печатной формы необходимо предусмотреть такую ситуацию, чтобы не возникало ошибок при обращении к данным.
  2. Приведение типов при составном реквизите: Если основанием могут выступать разные виды документов (например, и Реализация товаров и услуг, и Заказ покупателя), в запросе следует использовать конструкцию ВЫРАЗИТЬ(Заявка.ДокументОснование КАК Документ.РеализацияТоваровУслуг) либо объединять выборки через оператор ОБЪЕДИНИТЬ ВСЕ.
  3. Групповая печать: Всегда передавайте в параметры запроса массив ссылок (&МассивСсылок), а не единичную ссылку, чтобы стандартная команда печати из формы списка документов корректно обрабатывала выделение нескольких строк.
← На главную