Почему вычисляемое поле в СКД равно нулю при сложении с пустым значением и как настроить порядок колонок?

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

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

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

  1. Если в документе есть только товары (а услуг нет), то итоговая сумма НДС отображается как 0, хотя должна быть равна НДС по товарам.
  2. Колонка с итоговой суммой НДС появляется в отчете раньше, чем колонки с НДС по товарам и услугам, хотя в настройках она стоит последней.

Давайте подробно разберемся в причинах такого поведения и найдем решение.

Проблема 1: Вычисляемое поле возвращает ноль при сложении с пустым значением

Выясним причину этой ошибки. В языке запросов 1С (где иногда возникают трудности, если проводить сравнение строки с представлением ссылки) и в базах данных в целом существует специальное значение NULL. Оно означает не ноль, а отсутствие данных. Если в документе поступления нет услуг, то поле СуммаНДСУслуги будет равно NULL.

Ключевая особенность NULL заключается в том, что любая арифметическая операция с ним (сложение, вычитание и т.д.) в результате дает NULL. Например:

Система компоновки данных, получая итоговое значение NULL, при выводе в ячейку отчета интерпретирует его как 0. Вот почему мы видим ноль вместо ожидаемой суммы.

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

Синтаксис функции:

ЕСТЬNULL(ПроверяемоеВыражение, ЗначениеДляЗамены)

Она работает так: если ПроверяемоеВыражение равно NULL, функция вернет ЗначениеДляЗамены. В противном случае она вернет само значение ПроверяемогоВыражения.

В нашем случае, чтобы сложение работало корректно, нужно заменить некорректную формулу вычисляемого поля:

СуммаНДСТовары + СуммаНДСУслуги

На правильную, с обработкой возможных NULL:

ЕСТЬNULL(СуммаНДСТовары, 0) + ЕСТЬNULL(СуммаНДСУслуги, 0)

Теперь, если СуммаНДСУслуги окажется NULL, для расчета будет использован 0, и итоговая сумма посчитается верно.

Проблема 2: Неправильный порядок колонок и расчет итогов

Разберемся, почему колонка с вычисляемым полем "перескакивает" вперед. Причина кроется в фундаментальном понятии СКД (иногда в отчете могут использоваться две разных схемы) — ресурсах.

Когда вы объявляете поле ресурсом (на вкладке "Ресурсы" в схеме компоновки), СКД начинает относиться к нему по-особому. При построении макета отчета система обычно выводит колонки с ресурсами после полей группировок, а обычные (не ресурсные) поля — отдельно. Если СуммаНДСТовары и СуммаНДСУслуги объявлены ресурсами, а вычисляемое поле СуммаНДСИтог — нет, СКД считает его обычным полем и может вывести его в другом месте, нарушая задуманный порядок.

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

Решение — привести все числовые показатели к "общему знаменателю", то есть сделать их все ресурсами и правильно настроить выражения для расчета итогов.

Посмотрим на пошаговый алгоритм.

  1. Сделайте все числовые поля ресурсами. Перейдите на вкладку "Ресурсы" в конструкторе схемы компоновки данных. Убедитесь, что и исходные поля (СуммаНДСТовары, СуммаНДСУслуги), и ваше вычисляемое поле (например, назовем его СуммаНДСВсего) добавлены в список ресурсов.

  2. Задайте правильное выражение для ресурса. Для полей-ресурсов важно указать, как считать итоги. В колонке "Выражение" для нашего итогового поля нужно прописать формулу с использованием агрегатной функции Сумма(). Это гарантирует, что и в строках группировок, и в общем итоге отчета значения будут правильными.

    Корректное выражение для ресурса СуммаНДСВсего будет выглядеть так:

    Сумма(ЕСТЬNULL(СуммаНДСТовары, 0)) + Сумма(ЕСТЬNULL(СуммаНДСУслуги, 0))

    Либо, если вы уже создали вычисляемое поле СуммаНДСВсего с формулой ЕСТЬNULL(СуммаНДСТовары, 0) + ЕСТЬNULL(СуммаНДСУслуги, 0), то в выражении для ресурса можно написать проще:

    Сумма(СуммаНДСВсего)

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

  3. Настройте порядок полей. Теперь, когда все три поля являются ресурсами, перейдите в настройки отчета на вкладку "Выбранные поля". Расположите их в нужном порядке, например: СуммаНДСТовары, СуммаНДСУслуги, СуммаНДСВсего. СКД будет придерживаться этого порядка при выводе отчета.

Итоговый пример на основе запроса (быстрый анализ данных)

Проанализируем исходный запрос пользователя. Он получает данные из табличных частей "Товары" и "Услуги" документа.


ВЫБРАТЬ
    ПоступлениеТоваровУслуг.Ссылка КАК Ссылка,
    ПоступлениеТоваровУслуг.Контрагент КАК Контрагент,
    // Получаем сумму НДС по товарам
    ВложенныйЗапросТовары.СуммаНДСТовары,
    // Получаем сумму НДС по услугам
    ВложенныйЗапросУслуги.СуммаНДСУслуги
ИЗ
    Документ.ПоступлениеТоваровУслуг КАК ПоступлениеТоваровУслуг
        ЛЕВОЕ СОЕДИНЕНИЕ (ВЫБРАТЬ
            ПоступлениеТоваровУслугТовары.Ссылка КАК Ссылка,
            СУММА(ПоступлениеТоваровУслугТовары.СуммаНДС) КАК СуммаНДСТовары
        ИЗ
            Документ.ПоступлениеТоваровУслуг.Товары КАК ПоступлениеТоваровУслугТовары
        СГРУППИРОВАТЬ ПО
            ПоступлениеТоваровУслугТовары.Ссылка) КАК ВложенныйЗапросТовары
        ПО ПоступлениеТоваровУслуг.Ссылка = ВложенныйЗапросТовары.Ссылка
        ЛЕВОЕ СОЕДИНЕНИЕ (ВЫБРАТЬ
            ПоступлениеТоваровУслугУслуги.Ссылка КАК Ссылка,
            СУММА(ПоступлениеТоваровУслугУслуги.СуммаНДС) КАК СуммаНДСУслуги
        ИЗ
            Документ.ПоступлениеТоваровУслуг.Услуги КАК ПоступлениеТоваровУслугУслуги
        СГРУППИРОВАТЬ ПО
            ПоступлениеТоваровУслугУслуги.Ссылка) КАК ВложенныйЗапросУслуги
        ПО ПоступлениеТоваровУслуг.Ссылка = ВложенныйЗапросУслуги.Ссылка
ГДЕ
    ПоступлениеТоваровУслуг.ПометкаУдаления = ЛОЖЬ

В этом (улучшенном для примера) запросе мы получаем поля СуммаНДСТовары и СуммаНДСУслуги. Если для какого-то документа не будет записей в одной из табличных частей, левое соединение вернет NULL.

Дальнейшие действия в СКД:

  1. На вкладке "Вычисляемые поля" создаем поле СуммаНДСИтог с выражением ЕСТЬNULL(СуммаНДСТовары, 0) + ЕСТЬNULL(СуммаНДСУслуги, 0).
  2. На вкладке "Ресурсы" добавляем три поля: СуммаНДСТовары, СуммаНДСУслуги, СуммаНДСИтог. Для первых двух выражение будет Сумма(СуммаНДСТовары) и Сумма(СуммаНДСУслуги) соответственно. Для итогового поля — Сумма(СуммаНДСИтог).
  3. На вкладке "Настройки" в выбранных полях устанавливаем желаемый порядок колонок.

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

← На главную