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

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

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

Суть проблемы: коварство значения NULL

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

Если в вашем отчете по конкретной номенклатуре есть остаток, но не было прихода за период, поле Приход примет значение NULL. В итоге вся формула (NULL + 10) * 100 превратится в NULL, и в отчете вы увидите пустую ячейку.

Решение 1: Использование функции ЕСТЬNULL в запросе

Первый и самый надежный уровень решения — обработка данных на уровне запроса. Если вы используете пакетные запросы и временные таблицы, важно понимать, где именно нужно «подстелить соломку».

Рассмотрим типичную ошибку: программист добавляет ЕСТЬNULL внутри временных таблиц, но забывает про итоговое соединение. Разберем ситуацию на примере запроса:


// Временная таблица с закупками
ВЫБРАТЬ
    Закупки.Номенклатура,
    ЕСТЬNULL(Закупки.КоличествоОборот, 0) КАК Приход
ПОМЕСТИТЬ ВТ_Закупки
ИЗ
    РегистрНакопления.Закупки.Обороты(...) КАК Закупки;

////////////////////////////////////////////////////////////////////////////////
// Итоговый запрос
ВЫБРАТЬ
    Продажи.Номенклатура,
    ВТ_Закупки.Приход КАК Приход, // ОШИБКА: здесь может возникнуть NULL
    ВТ_Остатки.НачальныйОстаток КАК Остаток
ИЗ
    ВТ_Продажи КАК Продажи
    ЛЕВОЕ СОЕДИНЕНИЕ ВТ_Закупки КАК ВТ_Закупки
        ПО Продажи.Номенклатура = ВТ_Закупки.Номенклатура

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

Исправленный вариант итогового запроса:


ВЫБРАТЬ
    Продажи.Номенклатура,
    ЕСТЬNULL(ВТ_Закупки.Приход, 0) КАК Приход,
    ЕСТЬNULL(ВТ_Остатки.НачальныйОстаток, 0) КАК НачальныйОстаток,
    ЕСТЬNULL(ВТ_Цены.Цена, 0) КАК Цена
ИЗ
    ВТ_Продажи КАК Продажи
    ЛЕВОЕ СОЕДИНЕНИЕ ВТ_Закупки КАК ВТ_Закупки ПО Продажи.Номенклатура = ВТ_Закупки.Номенклатура
    ЛЕВОЕ СОЕДИНЕНИЕ ВТ_Остатки КАК ВТ_Остатки ПО Продажи.Номенклатура = ВТ_Остатки.Номенклатура
    ЛЕВОЕ СОЕДИНЕНИЕ ВТ_Цены КАК ВТ_Цены ПО Продажи.Номенклатура = ВТ_Цены.Номенклатура

Решение 2: Обработка NULL в вычисляемых полях СКД

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

(ЕстьNULL(Приход, 0) + ЕстьNULL(НачальныйОстаток, 0)) * ЕстьNULL(Цена, 0)

Такой подход гарантирует, что даже если данные по одному из компонентов отсутствуют, СКД подставит 0 и произведет расчет корректно.

Решение 3: Настройка ресурсов для корректных итогов

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

Проанализируем ситуацию: нам нужно умножить суммарное количество на среднюю или актуальную цену. В этом случае лучше перенести логику расчета на вкладку «Ресурсы».

  1. Оставьте поле в «Вычисляемых полях», но не пишите там сложную формулу, а просто укажите компоненты.
  2. На вкладке «Ресурсы» в колонке «Выражение» для вашего поля напишите:

Сумма(ЕстьNULL(Приход, 0) + ЕстьNULL(НачальныйОстаток, 0)) * Среднее(ЕстьNULL(Цена, 0))

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

Важные рекомендации при работе с соединениями

Выясним причину, почему данные могут пропадать вовсе. В запросах автора часто используется ЛЕВОЕ СОЕДИНЕНИЕ от таблицы Продажи. Это означает, что если товара не было в продажах, то он вообще не попадет в отчет, даже если он есть на остатках или приходил на склад.

Для полноценных складских отчетов рассмотрим более надежную методику:

Посмотрим на пример правильной группировки после объединения:


ВЫБРАТЬ
    Т.Номенклатура,
    СУММА(Т.Приход) КАК Приход,
    СУММА(Т.Остаток) КАК Остаток,
    МАКСИМУМ(Т.Цена) КАК Цена
ИЗ
    (ВЫБРАТЬ Номенклатура, Количество КАК Приход, 0 КАК Остаток... ИЗ Закупки
     ОБЪЕДИНИТЬ ВСЕ
     ВЫБРАТЬ Номенклатура, 0, Количество... ИЗ Остатки) КАК Т
СГРУППИРОВАТЬ ПО Т.Номенклатура

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

← На главную