Как в отчете Ведомость по товарам на складах в 1С:УТ 10.3 настроить расчет ресурсов по условию и добавить отбор по единице измерения?

Программист 1С v8.3 (Обычные формы) 1С:Управление торговлей Управленческий учет Торговля и дистрибуция
← На главную

В типовой конфигурации «1С:Управление торговлей 10.3» отчет «Ведомость по товарам на складах» построен на базе механизма Универсального отчета (использующего объект ПостроительОтчета). Нередко при доработке отчета под нестандартный учет возникает задача: пересчитывать остатки и обороты по разным формулам в зависимости от единицы измерения или коэффициента характеристики, а также добавить возможность быстрого отбора по единице измерения.

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

Анализ задачи и архитектуры универсального отчета

Проанализируем структуру данных: остатки в регистре накопления ТоварыНаСкладах хранятся в единицах хранения остатков. При формировании отчета построитель автоматически генерирует запрос к виртуальной таблице ТоварыНаСкладах.ОстаткиИОбороты (псевдоним ИсточникДанных).

Метод УниверсальныйОтчет.ДобавитьПолеРесурс() передает строку выражения напрямую в блок ВЫБРАТЬ итогового запроса. Поэтому любые условия в вычислениях ресурсов должны описываться конструкциями языка запросов 1С, а не встроенного языка 1С:Предприятие (то есть через ВЫБОР КОГДА ... ТОГДА ... ИНАЧЕ ... КОНЕЦ, а не через Если ... Тогда).

Шаг 1. Добавление условного расчета ресурсов через ДобавитьПолеРесурс

Посмотрим на типовую реализацию добавления ресурсов. Чтобы пересчет выполнялся по формуле деления на коэффициент характеристики только для определенных единиц (например, штук), а в остальных случаях умножался на коэффициент единицы хранения, используем ветвление в запросе.

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


// Добавление условных ресурсов для расчета остатков и оборотов
УниверсальныйОтчет.ДобавитьПолеРесурс("КоличествоБазовыхЕдНачальныйОстаток", 
    "ВЫБОР 
        КОГДА ИсточникДанных.Номенклатура.ЕдиницаХраненияОстатков.Наименование = ""шт"" 
            ТОГДА ИсточникДанных.КоличествоНачальныйОстаток / ВЫБОР КОГДА ЕСТЬNULL(ХарактеристикаНоменклатуры.Коэффициент, 0) = 0 ТОГДА 1 ИНАЧЕ ХарактеристикаНоменклатуры.Коэффициент КОНЕЦ
        ИНАЧЕ ИсточникДанных.КоличествоНачальныйОстаток * ИсточникДанных.Номенклатура.ЕдиницаХраненияОстатков.Коэффициент 
    КОНЕЦ", 
    "Количество (в базовых единицах) (нач. ост.)");

УниверсальныйОтчет.ДобавитьПолеРесурс("КоличествоБазовыхЕдПриход", 
    "ВЫБОР 
        КОГДА ИсточникДанных.Номенклатура.ЕдиницаХраненияОстатков.Наименование = ""шт"" 
            ТОГДА ИсточникДанных.КоличествоПриход / ВЫБОР КОГДА ЕСТЬNULL(ХарактеристикаНоменклатуры.Коэффициент, 0) = 0 ТОГДА 1 ИНАЧЕ ХарактеристикаНоменклатуры.Коэффициент КОНЕЦ
        ИНАЧЕ ИсточникДанных.КоличествоПриход * ИсточникДанных.Номенклатура.ЕдиницаХраненияОстатков.Коэффициент 
    КОНЕЦ", 
    "Количество (в базовых единицах) (приход)");

УниверсальныйОтчет.ДобавитьПолеРесурс("КоличествоБазовыхЕдРасход", 
    "ВЫБОР 
        КОГДА ИсточникДанных.Номенклатура.ЕдиницаХраненияОстатков.Наименование = ""шт"" 
            ТОГДА ИсточникДанных.КоличествоРасход / ВЫБОР КОГДА ЕСТЬNULL(ХарактеристикаНоменклатуры.Коэффициент, 0) = 0 ТОГДА 1 ИНАЧЕ ХарактеристикаНоменклатуры.Коэффициент КОНЕЦ
        ИНАЧЕ ИсточникДанных.КоличествоРасход * ИсточникДанных.Номенклатура.ЕдиницаХраненияОстатков.Коэффициент 
    КОНЕЦ", 
    "Количество (в базовых единицах) (расход)");

УниверсальныйОтчет.ДобавитьПолеРесурс("КоличествоБазовыхЕдКонечныйОстаток", 
    "ВЫБОР 
        КОГДА ИсточникДанных.Номенклатура.ЕдиницаХраненияОстатков.Наименование = ""шт"" 
            ТОГДА ИсточникДанных.КоличествоКонечныйОстаток / ВЫБОР КОГДА ЕСТЬNULL(ХарактеристикаНоменклатуры.Коэффициент, 0) = 0 ТОГДА 1 ИНАЧЕ ХарактеристикаНоменклатуры.Коэффициент КОНЕЦ
        ИНАЧЕ ИсточникДанных.КоличествоКонечныйОстаток * ИсточникДанных.Номенклатура.ЕдиницаХраненияОстатков.Коэффициент 
    КОНЕЦ", 
    "Количество (в базовых единицах) (кон. ост.)");

Важное замечание: При делении на реквизит ХарактеристикаНоменклатуры.Коэффициент всегда существует риск деления на ноль или получения NULL, если характеристика не выбрана или коэффициент не заполнен. Оборачивание делителя в конструкцию ВЫБОР КОГДА ЕСТЬNULL(..., 0) = 0 ТОГДА 1 ИНАЧЕ ... КОНЕЦ полностью предотвращает падение отчета с ошибкой времени выполнения.

Шаг 2. Добавление предопределенного отбора по единице измерения

Для предоставления пользователю возможности фильтровать данные по конкретной единице измерения номенклатуры в блок настройки отборов добавляется вызов метода ДобавитьОтбор().

Выясним правильный синтаксис обращения к реквизитам номенклатуры:


// Добавление предопределенных отборов отчета
УниверсальныйОтчет.ДобавитьОтбор("Склад");
УниверсальныйОтчет.ДобавитьОтбор("Номенклатура");
УниверсальныйОтчет.ДобавитьОтбор("Номенклатура.ЕдиницаХраненияОстатков", "Единица хранения остатков", Ложь);

В методе указываются:

  1. Путь к данным: Номенклатура.ЕдиницаХраненияОстатков (или Номенклатура.БазоваяЕдиницаИзмерения в зависимости от учетной логики).
  2. Пользовательское представление: строка с понятным именем поля в форме настроек.
  3. Флаг активности: значение Ложь указывает, что отбор будет доступен в списке, но по умолчанию флаг активности отбора снят.

Шаг 3. Правильный порядок инициализации в процедуре УстановитьНачальныеНастройки

Рассмотрим структуру процедуры УстановитьНачальныеНастройки целиком. Критически важно соблюдать последовательность вызовов методов универсального отчета:

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

Процедура УстановитьНачальныеНастройки(ДополнительныеПараметры = Неопределено) Экспорт

    УниверсальныйОтчет.мНазваниеОтчета = СокрЛП(ЭтотОбъект.Метаданные.Синоним);
    УниверсальныйОтчет.мВыбиратьИмяРегистра = Ложь;
    УниверсальныйОтчет.ИмяРегистра = "ТоварыНаСкладах";

    // Добавление пользовательских ресурсов с условием
    УниверсальныйОтчет.ДобавитьПолеРесурс("КоличествоБазовыхЕдНачальныйОстаток", 
        "ВЫБОР КОГДА ИсточникДанных.Номенклатура.ЕдиницаХраненияОстатков.Наименование = ""шт"" ТОГДА ИсточникДанных.КоличествоНачальныйОстаток / ВЫБОР КОГДА ЕСТЬNULL(ХарактеристикаНоменклатуры.Коэффициент, 0) = 0 ТОГДА 1 ИНАЧЕ ХарактеристикаНоменклатуры.Коэффициент КОНЕЦ ИНАЧЕ ИсточникДанных.КоличествоНачальныйОстаток * ИсточникДанных.Номенклатура.ЕдиницаХраненияОстатков.Коэффициент КОНЕЦ", 
        "Количество (в базовых единицах) (нач. ост.)");

    УниверсальныйОтчет.ДобавитьПолеРесурс("КоличествоБазовыхЕдКонечныйОстаток", 
        "ВЫБОР КОГДА ИсточникДанных.Номенклатура.ЕдиницаХраненияОстатков.Наименование = ""шт"" ТОГДА ИсточникДанных.КоличествоКонечныйОстаток / ВЫБОР КОГДА ЕСТЬNULL(ХарактеристикаНоменклатуры.Коэффициент, 0) = 0 ТОГДА 1 ИНАЧЕ ХарактеристикаНоменклатуры.Коэффициент КОНЕЦ ИНАЧЕ ИсточникДанных.КоличествоКонечныйОстаток * ИсточникДанных.Номенклатура.ЕдиницаХраненияОстатков.Коэффициент КОНЕЦ", 
        "Количество (в базовых единицах) (кон. ост.)");

    // Регистрация показателей для отображения колонок
    УниверсальныйОтчет.ДобавитьПоказатель("КоличествоБазовыхЕдНачальныйОстаток", "Начальный остаток", Истина, "ЧЦ=15; ЧДЦ=3", "КолБазовыхЕд", "Количество (в базовых единицах)");
    УниверсальныйОтчет.ДобавитьПоказатель("КоличествоБазовыхЕдКонечныйОстаток", "Конечный остаток", Истина, "ЧЦ=15; ЧДЦ=3", "КолБазовыхЕд", "Количество (в базовых единицах)");

    // Инициализация стандартных настроек построителя
    УниверсальныйОтчет.УстановитьНачальныеНастройки(Истина);

    // Установка измерений строк
    УниверсальныйОтчет.ДобавитьИзмерениеСтроки("Склад");
    УниверсальныйОтчет.ДобавитьИзмерениеСтроки("Номенклатура");

    // Установка предопределенных отборов
    УниверсальныйОтчет.ДобавитьОтбор("Склад");
    УниверсальныйОтчет.ДобавитьОтбор("Номенклатура");
    УниверсальныйОтчет.ДобавитьОтбор("Номенклатура.ЕдиницаХраненияОстатков", "Единица измерения", Ложь);

КонецПроцедуры

Альтернативный вариант: Полное переопределение текста запроса построителя

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

В такой ситуации рекомендуется отключить автоматическое определение запроса по регистру (закомментировать // УниверсальныйОтчет.ИмяРегистра = ...) и вручную передать сформированный оптимизированный текст в УниверсальныйОтчет.ПостроительОтчета.Текст, где все необходимые связи и расчеты будут выполнены во временных таблицах.

← На главную