Как в запросе 1С разделить отклонения на недостачу и излишки и вывести результат по группам номенклатуры?

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

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

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

Анализ ошибки синтаксиса: почему нельзя писать СУММА(А > Б)

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


Выбор Когда СУММА(КоличествоКнижн > КоличествоФакт) ТОГДА СУММА(КоличествоКнижн - КоличествоФакт) ИНАЧЕ 0 Конец КАК Недостача

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

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

Способ 1. Агрегация условных выражений по строкам

Если мы хотим вычислить недостачу и излишек для каждой исходной строки документа или регистра, а затем сложить их по группировке номенклатуры, поместим конструкцию ВЫБОР КОГДА внутрь функции СУММА. Это наиболее популярное решение:


ВЫБРАТЬ
    ИнвентаризацияТовары.Номенклатура КАК Номенклатура,
    СУММА(ИнвентаризацияТовары.КоличествоКнижн) КАК КоличествоКнижн,
    СУММА(ИнвентаризацияТовары.КоличествоФакт) КАК КоличествоФакт,
    СУММА(ВЫБОР 
            КОГДА ИнвентаризацияТовары.КоличествоКнижн > ИнвентаризацияТовары.КоличествоФакт 
                ТОГДА ИнвентаризацияТовары.КоличествоКнижн - ИнвентаризацияТовары.КоличествоФакт 
            ИНАЧЕ 0 
        КОНЕЦ) КАК Недостача,
    СУММА(ВЫБОР 
            КОГДА ИнвентаризацияТовары.КоличествоФакт > ИнвентаризацияТовары.КоличествоКнижн 
                ТОГДА ИнвентаризацияТовары.КоличествоФакт - ИнвентаризацияТовары.КоличествоКнижн 
            ИНАЧЕ 0 
        КОНЕЦ) КАК Излишки
ИЗ
    Документ.ИнвентаризацияТоваровНаСкладе.Товары КАК ИнвентаризацияТовары
СГРУППИРОВАТЬ ПО
    ИнвентаризацияТовары.Номенклатура

Обратим внимание: если в исходном документе одна и та же номенклатура встречается в нескольких строках (например, с разными характеристиками или сериями), этот способ рассчитает недостачи и излишки по каждой строке независимо. В результате по одной номенклатурной позиции могут одновременно заполниться и недостача, и излишек.

Способ 2. Расчет по свернутым итогам номенклатуры

Если нам необходимо, чтобы пересортица внутри позиций одной номенклатуры взаимно погашалась (то есть сначала считался общий книжный и фактический остаток по товару, а затем определялся общий результат), условие ВЫБОР следует вынести наружу по отношению к функциям СУММА:


ВЫБРАТЬ
    ИнвентаризацияТовары.Номенклатура КАК Номенклатура,
    СУММА(ИнвентаризацияТовары.КоличествоКнижн) КАК КоличествоКнижн,
    СУММА(ИнвентаризацияТовары.КоличествоФакт) КАК КоличествоФакт,
    ВЫБОР 
        КОГДА СУММА(ИнвентаризацияТовары.КоличествоКнижн) > СУММА(ИнвентаризацияТовары.КоличествоФакт) 
            ТОГДА СУММА(ИнвентаризацияТовары.КоличествоКнижн) - СУММА(ИнвентаризацияТовары.КоличествоФакт) 
        ИНАЧЕ 0 
    КОНЕЦ КАК Недостача,
    ВЫБОР 
        КОГДА СУММА(ИнвентаризацияТовары.КоличествоФакт) > СУММА(ИнвентаризацияТовары.КоличествоКнижн) 
            ТОГДА СУММА(ИнвентаризацияТовары.КоличествоФакт) - СУММА(ИнвентаризацияТовары.КоличествоКнижн) 
        ИНАЧЕ 0 
    КОНЕЦ КАК Излишки
ИЗ
    Документ.ИнвентаризацияТоваровНаСкладе.Товары КАК ИнвентаризацияТовары
СГРУППИРОВАТЬ ПО
    ИнвентаризацияТовары.Номенклатура

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


ВЫБРАТЬ
    ВложенныйЗапрос.Номенклатура КАК Номенклатура,
    ВложенныйЗапрос.КоличествоКнижн КАК КоличествоКнижн,
    ВложенныйЗапрос.КоличествоФакт КАК КоличествоФакт,
    ВЫБОР
        КОГДА ВложенныйЗапрос.Разница > 0 ТОГДА ВложенныйЗапрос.Разница
        ИНАЧЕ 0
    КОНЕЦ КАК Недостача,
    ВЫБОР
        КОГДА ВложенныйЗапрос.Разница < 0 ТОГДА -ВложенныйЗапрос.Разница
        ИНАЧЕ 0
    КОНЕЦ КАК Излишки
ИЗ
    (ВЫБРАТЬ
        ИнвентаризацияТовары.Номенклатура КАК Номенклатура,
        СУММА(ИнвентаризацияТовары.КоличествоКнижн) КАК КоличествоКнижн,
        СУММА(ИнвентаризацияТовары.КоличествоФакт) КАК КоличествоФакт,
        СУММА(ИнвентаризацияТовары.КоличествоКнижн - ИнвентаризацияТовары.КоличествоФакт) КАК Разница
    ИЗ
        Документ.ИнвентаризацияТоваровНаСкладе.Товары КАК ИнвентаризацияТовары
    СГРУППИРОВАТЬ ПО
        ИнвентаризацияТовары.Номенклатура) КАК ВложенныйЗапрос

Если в расчетах используются данные из внешних таблиц или результат левого соединения, не забываем оборачивать поля в функцию ЕСТЬNULL(Поле, 0), чтобы исключить влияние значений NULL на результат арифметических операций.

Вывод данных по группам товаров в табличный документ

Разберем по шагам, как вывести полученный отчет с иерархией групп справочника Номенклатура.

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

Также эту задачу удобно решать с помощью Системы компоновки данных (СКД). Для этого поля Недостача и Излишки объявляются на вкладке «Ресурсы» с выражениями Сумма(Недостача) и Сумма(Излишки), а в настройках структуры отчета для группировки Номенклатура выбирается тип Иерархия. СКД самостоятельно построит дерево групп и выведет его в ТабличныйДокумент.

← На главную