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

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

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

Разбор основной причины: влияние значений NULL

Самая распространенная причина, по которой умножение «не работает» — это наличие значений NULL в одном из операндов. В языке запросов 1С и выражениях СКД любая арифметическая операция с NULL всегда дает в результате NULL. Рассмотрим ситуацию: если вы выполняете левое соединение с регистром коэффициентов и для какой-то строки данных коэффициент не найден, поле будет содержать NULL. При умножении суммы на этот «пустой» коэффициент вся сумма превратится в пустоту.

Рассмотрим пример кода, который часто используют разработчики в попытке обойти эту проблему:


ВЫБОР
    КОГДА ЕСТЬNULL(Коэффициент, 0) = 0
        ТОГДА СуммаНалога
    ИНАЧЕ СуммаНалога * ЕСТЬNULL(Коэффициент, 0)
КОНЕЦ КАК СуммаК

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

Корректная обработка NULL при умножении

При сложении замена NULL на 0 оправдана. Однако при умножении лучше использовать замену на 1, если логика подразумевает сохранение исходного числа при отсутствии коэффициента. Выясним, как упростить выражение для вычисляемого поля или запроса:

ЕСТЬNULL(СуммаНалога, 0) * ЕСТЬNULL(Коэффициент, 1)

Этот подход гарантирует, что если коэффициент не задан (NULL), число будет умножено на единицу, что сохранит его значение. Рассмотрим подробнее, почему даже при правильном ЕСТЬNULL в запросе отчет может врать.

Критическая важность настройки ресурсов СКД

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

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

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


// В поле Выражение для ресурса ЗначениеК
Максимум(ЗначениеК)

После этого итоговое поле СуммаК в ресурсах должно рассчитываться не как сумма уже перемноженных значений, а как произведение итоговой суммы на итоговый коэффициент (если это предусмотрено бизнес-логикой):


// В поле Выражение для ресурса СуммаК
Сумма(СуммаНалога) * Максимум(ЗначениеК)

Проблема виртуальных таблиц и параметров

Выясним причину, связанную с использованием виртуальных таблиц, таких как СрезПоследних. В СКД виртуальные таблицы могут вести себя нестабильно, если явно не указать им параметр Период. Если в запросе вы просто соединяете таблицу с РегистрСведений.ИмяРегистра.СрезПоследних, СКД может подставить туда стандартный параметр &Период. Если же этот параметр в настройках отчета не заполнен или имеет тип СтандартныйПериод, виртуальная таблица может вернуть пустые значения (NULL), что приведет к сбою умножения.

Посмотрим на пример правильного оформления виртуальной таблицы в тексте запроса СКД:


ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.Коэффициенты.СрезПоследних(&ДатаСреза, ) КАК КоэффициентыСрезПоследних
ПО ОсновнаяТаблица.Ключ = КоэффициентыСрезПоследних.Ключ

Обязательно проверьте на вкладке Параметры, чтобы &ДатаСреза заполнялась корректно (например, выражением &Период.ДатаОкончания).

Использование вычисляемых полей

Если расчет в запросе по-прежнему вызывает трудности, перенесем логику в Вычисляемые поля. Это часто помогает, когда данные для расчета приходят из разных наборов данных. Рассмотрим пример выражения для вычисляемого поля:


ВЫБОР 
    КОГДА ЗначениеК = 0 ИЛИ ЗначениеК ЕСТЬ NULL 
    ТОГДА СуммаНалога 
    ИНАЧЕ СуммаНалога * ЗначениеК 
КОНЕЦ

Важный нюанс: в вычисляемых полях СКД функции ЕСТЬNULL работают аналогично языку запросов, но обращение к полям происходит напрямую по их именам, заданным в наборе данных. Если поле ЗначениеК само является результатом другого вычисляемого поля, убедитесь в порядке их следования в списке.

Итоговый алгоритм проверки

Если вы столкнулись с тем, что произведение в СКД не выполняется, пройдите по следующим шагам:

  1. Проанализируем данные через Консоль запросов. Если там умножение работает, значит, проблема в настройках компоновки (ресурсах или связях).
  2. Проверим типы данных. Убедимся, что оба поля имеют тип Число.
  3. Заменим в формуле умножения коэффициент на статичное число (например, 2). Если результат изменился — значит, проблема в получении коэффициента (он приходит как NULL или 0).
  4. Проверим вкладку Ресурсы. Убедимся, что для коэффициента не стоит функция Сумма, а для итогового расчетного поля формула агрегации соответствует математической логике отчета.
  5. Убедимся, что в настройках полей набора данных не стоит ограничений на использование поля в расчетах.

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

← На главную