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