Как заменить NULL на ноль при связи наборов данных в СКД

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

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

Почему формулы ресурсов и отборы работают неожиданно

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

  1. Ресурсы не рассчитываются для детальных записей. Если в отчете выводятся простые детальные записи без группировок, формулы, прописанные на вкладке Ресурсы (например, Сумма(ЕстьNull(Количество, 0))), просто не вызываются. Платформа берет исходные «сырые» данные из набора, оставляя в поле значение NULL. Ресурсы рассчитываются только для строк итогов и группировок.
  2. Трансляция глобального отбора в подчиненный запрос. Когда отбор настраивается в корне настроек отчета (на самом верхнем уровне), процессор компоновки данных оптимизирует выполнение и «спускает» условие отбора напрямую в запрос подчиненного набора данных. В результате соединение фактически превращается из левого во внутреннее: строки ведущего набора отсекаются еще до того, как объединятся в памяти.
  3. Особенности операций с NULL. В языке выражений СКД любая арифметическая операция с неопределенным значением (например, Поле1 - Поле2, где одно из полей равно NULL) всегда возвращает NULL. Прямые проверки в условном оформлении вида Поле = 0 также не срабатывают, поскольку NULL не равен нулю.

Способ 1. Использование вычисляемых и пользовательских полей

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

Разберем по шагам настройку вычисляемого поля:

  1. Перейдем на вкладку Вычисляемые поля в схеме компоновки данных.
  2. Добавим новую строку и зададим Путь к данным, например, КоличествоБезNull.
  3. В колонке Выражение укажем функцию замены: ЕстьNull(Количество, 0)
  4. Если необходимо производить вычитание или сложение полей из разных наборов данных, создадим отдельное вычисляемое поле, например, РазницаКоличеств: ЕстьNull(КоличествоНабор1, 0) - ЕстьNull(КоличествоНабор2, 0)
  5. Если поле является числовым показателем, перейдем на вкладку Ресурсы и назначим для созданного вычисляемого поля расчет итогов по группировкам: Сумма(КоличествоБезNull)

Аналогичным образом пользователь в режиме предприятия может создать Пользовательское поле - выражение на вкладке настроек отчета, прописав аналогичное выражение в поле выражения и выражении итогов.

Способ 2. Замена отображения через условное оформление

Когда числовые расчеты не требуются, а цель состоит лишь в том, чтобы не показывать пустую ячейку в отчете и вывести на печать цифру 0, создавать лишние поля не обязательно. Достаточно применить условное оформление.

Посмотрим на пример настройки:

  1. Откроем вкладку Настройки и перейдем на вкладку Условное оформление (на уровне отчета или конкретной группировки).
  2. Добавим новый элемент оформления.
  3. На вкладке Условие выберем наше поле подчиненного набора, вид сравнения установим в Не заполнено.
  4. На вкладке Оформляемые поля добавим проверяемое поле.
  5. На вкладке Оформление активируем параметр Текст и зададим значение 0.

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

Способ 3. Корректный отбор по отсутствующим данным

Частая задача разработчика — вывести элементы главного набора, по которым во втором наборе нет никаких данных (например, номенклатуру без движений по регистру). Если установить отбор Поле НЕ Заполнено в общих настройках отчета, отчет вернет пустой результат из-за трансляции условия в подчиненный запрос.

Выясним причину и применим правильный алгоритм настройки:

  1. Перейдем в структуре отчета к конкретной группировке или пункту Детальные записи.
  2. В нижней части окна перейдем на локальную вкладку Отбор именно этой группировки (не путать с общим отбором всего отчета).
  3. Добавим условие: ИмяПоляВторогоНабора НЕ Заполнено.
  4. Проверим дополнительные свойства группировки: убедимся, что параметр Игнорировать значения NULL выключен (флаг снят).

Локальный отбор группировки применяется процессором компоновки постфактум — в оперативной памяти после того, как объединение наборов уже завершено. Это гарантирует сохранение всех строк левого соединения.

Способ 4. Переход на один набор данных или объединение

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

Рассмотрим альтернативные архитектурные решения:

  1. Объединение запросов через временные таблицы: поместим выборку первого источника и второго источника во временные таблицы внутри одного набора данных Запрос. При левом соединении используем стандартный оператор ЕСТЬNULL() прямо в коде запроса.
  2. Набор данных «Объединение»: если нужно сопоставить остатки или обороты разных регистров, создадим единый родительский Набор данных - объединение. Внутрь него добавим отдельные наборы-запросы с одинаковым составом полей, где отсутствующие показатели заполняются нулями. Это полностью исключит появление неопределенных значений при формировании отчета.
← На главную