При разработке печатных форм для документов, у которых нет собственной табличной части (например, Заявка на доставку), часто возникает задача вывести перечень номенклатуры из документа-основания (например, Реализация товаров и услуг). Рассмотрим распространенные ошибки начинающих разработчиков и разберем правильные способы реализации такого механизма.
Штатный конструктор печати платформы 1С умеет оперировать только реквизитами и собственными табличными частями того объекта конфигурации, для которого генерируется макет. Получение строк из документа-основания всегда требует ручной доработки текста запроса и процедур вывода в табличный документ.
Проанализируем частые ошибки, возникающие при попытке получить строки табличной части документа-основания:
Заявка.ДокументОснование.Товары в языке запросов 1С является синтаксически неверной. Табличные части не хранятся внутри ссылки объекта — они представляют собой отдельные физические таблицы базы данных.ИЗ: Нельзя писать ИЗ Документ.ДокументОснование. В секции источников данных указываются только реальные имена объектов метаданных конфигурации, например Документ.ЗаявкаНаДоставку или Документ.РеализацияТоваровУслуг.Товары.ДокументОснование имеет составной тип данных, прямое соединение может привести к неоптимальному плану выполнения или ошибкам. В таких ситуациях обязательно применяется конструкция ВЫРАЗИТЬ().ПолучитьДокумент()) или несоответствие переменных запроса и выборки приводят к аварийному завершению выполнения процедуры.Разберем классический вариант построения запроса, в котором к таблице шапки текущего документа присоединяется табличная часть документа-основания. Выясним, как правильно связать таблицы по ссылке основания и выполнить обход с помощью группировок.
Посмотрим на пример текста запроса и процедуры вывода:
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Заявка.Ссылка КАК Ссылка,
| Заявка.Номер КАК Номер,
| Заявка.Дата КАК Дата,
| Заявка.ДокументОснование КАК ДокументОснование,
| ТоварыРеализации.НомерСтроки КАК НомерСтроки,
| ТоварыРеализации.Номенклатура КАК Номенклатура,
| ТоварыРеализации.Количество КАК Количество,
| ТоварыРеализации.Цена КАК Цена,
| ТоварыРеализации.Сумма КАК Сумма
|ИЗ
| Документ.ЗаявкаНаДоставку КАК Заявка
| ЛЕВОЕ СОЕДИНЕНИЕ Документ.РеализацияТоваровУслуг.Товары КАК ТоварыРеализации
| ПО Заявка.ДокументОснование = ТоварыРеализации.Ссылка
|ГДЕ
| Заявка.Ссылка В (&МассивСсылок)
|ИТОГИ ПО
| Ссылка";
Запрос.УстановитьПараметр("МассивСсылок", МассивСсылок);
РезультатЗапроса = Запрос.Выполнить();
ОбластьШапка = Макет.ПолучитьОбласть("Шапка");
ОбластьТоварыШапка = Макет.ПолучитьОбласть("ТоварыШапка");
ОбластьТовары = Макет.ПолучитьОбласть("Товары");
ОбластьПодвал = Макет.ПолучитьОбласть("Подвал");
ВыборкаДокумент = РезультатЗапроса.Выбрать(ОбходРезультатаЗапроса.ПоГруппировкам);
Пока ВыборкаДокумент.Следующий() Цикл
ОбластьШапка.Параметры.Заполнить(ВыборкаДокумент);
ТабДок.Вывести(ОбластьШапка);
ТабДок.Вывести(ОбластьТоварыШапка);
ВыборкаСтроки = ВыборкаДокумент.Выбрать();
Пока ВыборкаСтроки.Следующий() Цикл
// Проверяем, есть ли заполненная строка ТЧ
Если ЗначениеЗаполнено(ВыборкаСтроки.Номенклатура) Тогда
ОбластьТовары.Параметры.Заполнить(ВыборкаСтроки);
ТабДок.Вывести(ОбластьТовары);
КонецЕсли;
КонецЦикла;
ОбластьПодвал.Параметры.Заполнить(ВыборкаДокумент);
ТабДок.Вывести(ОбластьПодвал);
КонецЦикла;
Рассмотрим еще один рекомендуемый стандарт разработки — использование пакетного запроса через менеджер временных таблиц. Этот подход особенно удобен, когда структура печатной формы сложная или документ-основание может содержать несколько табличных частей.
Разберем по шагам логику работы пакета:
ЗаявкаНаДоставку и помещаются во временную таблицу.РеализацияТоваровУслуг.Товары выбираются напрямую с отбором по ссылке из временной таблицы.ВыполнитьПакет(), возвращая отдельные выборки для шапки и строк.Посмотрим на пример реализации пакетного запроса:
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Заявка.Ссылка КАК Ссылка,
| Заявка.Номер КАК Номер,
| Заявка.Дата КАК Дата,
| Заявка.ДокументОснование КАК ДокументОснование
|ПОМЕСТИТЬ ВТ_Заявки
|ИЗ
| Документ.ЗаявкаНаДоставку КАК Заявка
|ГДЕ
| Заявка.Ссылка В (&МассивСсылок)
|;
|
|////////////////////////////////////////////////////////////////////////////////
|ВЫБРАТЬ
| ВТ_Заявки.Ссылка КАК Ссылка,
| ВТ_Заявки.Номер КАК Номер,
| ВТ_Заявки.Дата КАК Дата,
| ВТ_Заявки.ДокументОснование КАК ДокументОснование
|ИЗ
| ВТ_Заявки КАК ВТ_Заявки
|;
|
|////////////////////////////////////////////////////////////////////////////////
|ВЫБРАТЬ
| Товары.Ссылка КАК ДокументОснование,
| Товары.НомерСтроки КАК НомерСтроки,
| Товары.Номенклатура КАК Номенклатура,
| Товары.Количество КАК Количество,
| Товары.Цена КАК Цена,
| Товары.Сумма КАК Сумма
|ИЗ
| Документ.РеализацияТоваровУслуг.Товары КАК Товары
|ГДЕ
| Товары.Ссылка В
| (ВЫБРАТЬ
| ВТ_Заявки.ДокументОснование
| ИЗ
| ВТ_Заявки КАК ВТ_Заявки)";
Запрос.УстановитьПараметр("МассивСсылок", МассивСсылок);
МассивРезультатов = Запрос.ВыполнитьПакет();
ВыборкаШапка = МассивРезультатов[1].Выбрать();
ТаблицаТовары = МассивРезультатов[2].Выгрузить();
Пока ВыборкаШапка.Следующий() Цикл
ОбластьШапка = Макет.ПолучитьОбласть("Шапка");
ОбластьШапка.Параметры.Заполнить(ВыборкаШапка);
ТабДок.Вывести(ОбластьШапка);
ТабДок.Вывести(Макет.ПолучитьОбласть("ТоварыШапка"));
ОбластьСтроки = Макет.ПолучитьОбласть("Товары");
Отбор = Новый Структура("ДокументОснование", ВыборкаШапка.ДокументОснование);
НайденныеСтроки = ТаблицаТовары.НайтиСтроки(Отбор);
Для Каждого СтрокаТЧ Из НайденныеСтроки Цикл
ОбластьСтроки.Параметры.Заполнить(СтрокаТЧ);
ТабДок.Вывести(ОбластьСтроки);
КонецЦикла;
ТабДок.Вывести(Макет.ПолучитьОбласть("Подвал"));
КонецЦикла;
При реализации вывода данных из связанных документов обязательно учитывайте следующие моменты:
ДокументОснование будет пустой ссылкой. В коде формирования печатной формы необходимо предусмотреть такую ситуацию, чтобы не возникало ошибок при обращении к данным.ВЫРАЗИТЬ(Заявка.ДокументОснование КАК Документ.РеализацияТоваровУслуг) либо объединять выборки через оператор ОБЪЕДИНИТЬ ВСЕ.&МассивСсылок), а не единичную ссылку, чтобы стандартная команда печати из формы списка документов корректно обрабатывала выделение нескольких строк.