Как перевести отчет с ПостроителяОтчета на Систему Компоновки Данных (СКД) и корректно настроить отборы и проценты?

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

Переход от старого ПостроителяОтчета к современной Системе Компоновки Данных (СКД) в 1С v8.3 часто вызывает сложности, особенно когда речь идет об адаптации существующих запросов, корректном расчете агрегированных показателей (например, процентов от общих продаж) и установке предопределенных отборов. Давайте разберем эту задачу по шагам, выяснив, как эффективно использовать возможности СКД для решения подобных проблем.

Адаптация существующего запроса для СКД

Когда мы переносим запрос из ПостроителяОтчета в СКД, нам необходимо помнить, что СКД имеет свой собственный, более мощный и гибкий механизм обработки данных. Это означает, что некоторые конструкции, специфичные для ПостроителяОтчета, следует удалить или переосмыслить.

  1. Удаление секции "ИТОГИ" и "ПО"

    Важным шагом является удаление секции ИТОГИ и ПО из вашего запроса. ПостроительОтчета использовал их для формирования итоговых строк и группировок. СКД, в свою очередь, предоставляет собственный, гораздо более мощный механизм для построения итогов, группировок и иерархии, который настраивается отдельно в схеме компоновки данных. Если вы оставите эту секцию, при попытке вставить запрос в СКД, система выдаст ошибку или предупреждение, как это случилось в обсуждаемой ситуации. Пользователь форума подтвердил, что именно удаление этих секций помогло адаптировать запрос.

  2. Корректное определение параметров

    Убедитесь, что все параметры, которые используются в вашем запросе, такие как &НачПер, &КонПер, &Организация, &Сч9001 и другие, корректно определены в свойствах набора данных схемы компоновки данных. Для каждого параметра необходимо указать его тип, доступность и, при необходимости, предоставить ему значение по умолчанию или связать с пользовательским полем ввода. Если параметры не заданы или заданы неверно, запрос в консоли запросов или в отчете СКД может возвращать пустые данные или ошибаться. Именно с этой проблемой столкнулся автор темы, когда запрос не выводил ничего в консоли.

  3. Работа с временными таблицами и вложенными запросами

    СКД прекрасно работает с вложенными запросами и временными таблицами (конструкция ВЫБРАТЬ ... ИЗ (...) КАК ИмяТаблицы). В вашем запросе используется несколько таких конструкций (Sales, PrimeCost, AllSales), что является стандартной практикой и не должно вызывать проблем при адаптации для СКД, если они синтаксически верны. Рассмотрим исходный запрос, чтобы понять его структуру:

    
    ВЫБРАТЬ
        Sales.Номенклатура КАК Номенклатура,
        Sales.Контрагент КАК Покупатель,
        Sales.ДоговорКонтрагента КАК ДоговорКонтрагента,
        СУММА(Sales.Количество) КАК Количество,
        СУММА(Sales.Сумма) КАК Net_Sales_YTD,
        СРЕДНЕЕ(Sales.Цена) КАК Цена,
        Sales.Регистратор КАК Регистратор,
        ВЫРАЗИТЬ(Sales.Сумма - Sales.Количество * PrimeCost.ЦенаСебест КАК ЧИСЛО(15, 2)) КАК GP1_RUB,
        ВЫБОР
            КОГДА Sales.Количество * PrimeCost.ЦенаСебест = 0
            ТОГДА 0
            ИНАЧЕ ВЫРАЗИТЬ(Sales.Сумма * 100 / (Sales.Количество * PrimeCost.ЦенаСебест) - 100 КАК ЧИСЛО(15, 2))
        КОНЕЦ КАК GP1_Percent,
        PrimeCost.ЦенаСебест КАК ЦенаСебест,
        ВЫРАЗИТЬ(Sales.Количество * PrimeCost.ЦенаСебест КАК ЧИСЛО(15, 2)) КАК COGS,
        СУММА(ВЫБОР
            КОГДА AllSales.Сумма = 0
            ТОГДА 0
            ИНАЧЕ ВЫРАЗИТЬ(Sales.Сумма / AllSales.Сумма * 100 КАК ЧИСЛО(15, 2))
        КОНЕЦ) КАК Bayers_Share_In_Total_Net_Sales
    ИЗ
        (ВЫБРАТЬ
            ХозрасчетныйОборотыДтКт.СубконтоКт3 КАК Номенклатура,
            ХозрасчетныйОборотыДтКт.СубконтоДт1 КАК Контрагент,
            ХозрасчетныйОборотыДтКт.СубконтоДт2 КАК ДоговорКонтрагента,
            ХозрасчетныйОборотыДтКт.КоличествоОборотКт КАК Количество,
            ХозрасчетныйОборотыДтКт.СуммаОборот КАК Сумма,
            ВЫБОР
                КОГДА ХозрасчетныйОборотыДтКт.КоличествоОборотКт = 0
                ТОГДА 0
                ИНАЧЕ ВЫРАЗИТЬ(ЕСТЬNULL(ХозрасчетныйОборотыДтКт.СуммаОборот, 0) / ХозрасчетныйОборотыДтКт.КоличествоОборотКт КАК ЧИСЛО(15, 2))
            КОНЕЦ КАК Цена,
            ХозрасчетныйОборотыДтКт.Регистратор КАК Регистратор
        ИЗ
            РегистрБухгалтерии.Хозрасчетный.ОборотыДтКт(&НачПер, &КонПер, Регистратор, , , СчетКт = &Сч9001, , Организация = &Организация) КАК ХозрасчетныйОборотыДтКт) КАК Sales
            ЛЕВОЕ СОЕДИНЕНИЕ (ВЫБРАТЬ
                ХозрасчетныйОборотыДтКт.КоличествоОборотКт КАК Количество,
                ХозрасчетныйОборотыДтКт.СуммаОборот КАК Сумма,
                ХозрасчетныйОборотыДтКт.СубконтоКт1 КАК Номенклатура,
                ВЫБОР
                    КОГДА ХозрасчетныйОборотыДтКт.КоличествоОборотКт = 0
                    ТОГДА 0
                    ИНАЧЕ ХозрасчетныйОборотыДтКт.СуммаОборот / ХозрасчетныйОборотыДтКт.КоличествоОборотКт
                КОНЕЦ КАК ЦенаСебест
            ИЗ
                РегистрБухгалтерии.Хозрасчетный.ОборотыДтКт(
                    &НачПер,
                    &КонПер,
                    Период,
                    СчетДт = &Сч9002
                        ИЛИ СчетДт = &Сч9102,
                    ,
                    СчетКт = &Сч43
                        ИЛИ СчетКт = &Сч4101
                        ИЛИ СчетКт = &Сч4104
                        ИЛИ СчетКт = &Сч10,
                    ,
                    Организация = &Организация) КАК ХозрасчетныйОборотыДтКт) КАК PrimeCost
            ПО Sales.Номенклатура = PrimeCost.Номенклатура
            ЛЕВОЕ СОЕДИНЕНИЕ (ВЫБРАТЬ
                СУММА(ХозрасчетныйОборотыДтКт.СуммаОборот) КАК Сумма
            ИЗ
                РегистрБухгалтерии.Хозрасчетный.ОборотыДтКт(&НачПер, &КонПер, Регистратор, , , СчетКт = &Сч9001, , Организация = &Организация) КАК ХозрасчетныйОборотыДтКт) КАК AllSales
            ПО (ИСТИНА)
    
    СГРУППИРОВАТЬ ПО
        Sales.Номенклатура,
        Sales.Контрагент,
        Sales.ДоговорКонтрагента,
        Sales.Регистратор,
        PrimeCost.ЦенаСебест,
        ВЫРАЗИТЬ(Sales.Сумма - Sales.Количество * PrimeCost.ЦенаСебест КАК ЧИСЛО(15, 2)),
        ВЫБОР
            КОГДА Sales.Количество * PrimeCost.ЦенаСебест = 0
            ТОГДА 0
            ИНАЧЕ ВЫРАЗИТЬ(Sales.Сумма * 100 / (Sales.Количество * PrimeCost.ЦенаСебест) - 100 КАК ЧИСЛО(15, 2))
        КОНЕЦ,
        ВЫРАЗИТЬ(Sales.Количество * PrimeCost.ЦенаСебест КАК ЧИСЛО(15, 2))
    ИТОГИ
        СУММА(Количество),
        СУММА(Net_Sales_YTD),
        СРЕДНЕЕ(Цена),
        СУММА(GP1_RUB),
        СРЕДНЕЕ(GP1_Percent),
        СРЕДНЕЕ(ЦенаСебест),
        СУММА(COGS),
        СУММА(Bayers_Share_In_Total_Net_Sales)
    ПО
        ОБЩИЕ,
        Покупатель
    

    Как мы видим, этот запрос содержит все упомянутые элементы. В СКД нам потребуется удалить секцию ИТОГИ ... ПО ... и, как мы увидим далее, подзапрос AllSales.

    Корректный расчет процента от общих продаж при наличии отбора

    Основная проблема, с которой столкнулся автор темы, заключалась в неверном расчете процента от общих продаж при применении отборов. Процент считался от "истинного" общего итога по всем данным, а не от "отфильтрованного" итога, то есть от тех данных, которые попали в отчет после применения отбора. СКД позволяет легко решить эту проблему благодаря своим мощным возможностям агрегации.

    1. Удаление подзапроса AllSales и условия ПО (ИСТИНА)

      В исходном запросе для получения общей суммы используется подзапрос AllSales и странное условие соединения ПО (ИСТИНА). Этот подзапрос извлекает сумму продаж по всем данным без учета потенциальных отборов, которые могут быть применены в пользовательском интерфейсе. В СКД такой подход не только избыточен, но и неверен для расчета процента от фильтрованного итога. СКД способна самостоятельно вычислить общий итог по текущему набору данных, который уже включает все примененные отборы. Поэтому мы рекомендуем удалить подзапрос AllSales и соответствующее левое соединение из текста запроса, который будет использоваться в СКД.

    2. Создание вычисляемого поля в СКД

      Чтобы получить процент от общего итога по отфильтрованным данным, необходимо создать вычисляемое поле непосредственно в СКД, а не пытаться реализовать это в тексте запроса. Давайте рассмотрим, как это сделать:

      1. В настройках схемы компоновки данных перейдите на вкладку "Вычисляемые поля".

      2. Добавьте новое вычисляемое поле, например, с именем ПроцентОтОбщихПродаж.

      3. В качестве выражения для этого поля укажите следующую формулу:

        Сумма(Net_Sales_YTD) / СУММА(Net_Sales_YTD) ОБЩИЙ ИТОГ * 100

        Разберем эту формулу:

        • Сумма(Net_Sales_YTD) будет возвращать сумму продаж для текущей строки или группы, в зависимости от группировки отчета.
        • СУММА(Net_Sales_YTD) ОБЩИЙ ИТОГ (или SUM(Net_Sales_YTD) TOTAL в англоязычных конфигурациях) — это специальная агрегатная функция СКД, которая возвращает сумму по всему набору данных после применения всех отборов. Таким образом, эта функция всегда будет учитывать только те данные, которые видны в отчете.

        При использовании такого вычисляемого поля, процент будет всегда рассчитываться относительно суммы, видимой в отчете, и при любом отборе сумма процентов по всему отчету (или по каждой крупной группе, если так настроено) будет составлять 100%.

    Установка предопределенного отбора по группе номенклатуры в СКД

    Автор темы также интересовался, как сделать так, чтобы отчет всегда формировался с отбором по определенной группе номенклатуры без участия пользователя, то есть с предопределенным или "жестким" отбором. СКД предоставляет удобные инструменты для такой настройки.

    1. Настройка фиксированного отбора

      В режиме конфигурирования (или в пользовательском режиме, если это разрешено и сохраняется), в настройках схемы компоновки данных перейдите на вкладку "Настройки" или "Основные настройки". Здесь вы можете добавить новый элемент отбора. Пользователь форума также получил подтверждение, что это возможно сделать в настройках СКД.

    2. Условие отбора по группе

      Для поля Номенклатура выберите тип сравнения В группе из списка (или просто В группе, в зависимости от версии платформы). В качестве значения укажите нужную группу номенклатуры (например, "net sales film") из справочника. Это позволит отобрать все элементы, находящиеся в указанной группе и ее подгруппах.

    3. Включение иерархии

      Если необходимо, чтобы отбор включал элементы из подгрупп, убедитесь, что для поля "Номенклатура" в СКД включена иерархия. Это обычно настраивается в свойствах поля на вкладке "Наборы данных" или "Поля". Включив иерархию, вы гарантируете, что при отборе по группе будут учтены все вложенные элементы и подгруппы.

    4. Фиксированные настройки против пользовательских

      Если вы хотите, чтобы пользователь видел этот отбор, но не мог его изменять, вы можете добавить его в "Пользовательские настройки" с ограничением редактирования. Однако, если отбор должен быть "жестким" и невидимым для изменения пользователем, его лучше оставить в фиксированных настройках схемы. В этом случае отчет будет всегда формироваться с этим отбором автоматически, без дополнительных действий со стороны пользователя.

    Следуя этим шагам, вы сможете успешно перевести ваш отчет с ПостроителяОтчета на СКД, корректно настроить расчет процентов отфильтрованных данных и установить необходимые предопределенные отборы, значительно повысив гибкость и функциональность вашего отчета.

← На главную