Почему булево поле не выгружается в строки-группы дерева значений и как это исправить?

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

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

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

Причина появления NULL в группировочных строках

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

  1. Перечислены в секции группировок ИТОГИ ... ПО.
  2. Явно рассчитываются с помощью агрегатных функций (СУММА, МАКСИМУМ, МИНИМУМ, КОЛИЧЕСТВО) в секции ИТОГИ.

Если поле не указано в блоке итогов, то на уровне группировочной записи оно не вычисляется вовсе и принимает значение NULL. При выгрузке в дерево значений колонка в строке-родителе остается пустой.

Кроме того, разработчики часто пытаются применить к логическому полю функцию СУММА(), что приводит к синтаксической ошибке, поскольку агрегатная функция суммы в языке запросов 1С не поддерживает тип Булево.

Способ 1. Использование функций МАКСИМУМ и МИНИМУМ в итогах

Разберем наиболее простое и быстрое решение. Язык запросов 1С поддерживает применение агрегатных функций МАКСИМУМ и МИНИМУМ к булевым полям без необходимости преобразования их в числа.

Посмотрим на логику работы этих функций с булевыми значениями:

  1. МАКСИМУМ(ПолеБулево) — работает по принципу логического ИЛИ. Если хотя бы в одной строке подчиненной группы значение равно Истина, родительская строка получит значение Истина.
  2. МИНИМУМ(ПолеБулево) — работает по принципу логического И. Значение Истина будет установлено в родителе только тогда, когда во всех подчиненных строках значение равно Истина (если хотя бы в одной строке Ложь, результат будет Ложь).

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


ВЫБРАТЬ
    ЗаказКлиентаТовары.Ссылка КАК Документ,
    ЗаказКлиентаТовары.Номенклатура КАК Номенклатура,
    ЗаказКлиентаТовары.Отменено КАК ФлагОтмены
ИЗ
    Документ.ЗаказКлиента.Товары КАК ЗаказКлиентаТовары

ИТОГИ
    МАКСИМУМ(ФлагОтмены)
ПО
    Документ

Способ 2. Включение поля в список группировок шапки

Если логическое поле является реквизитом самого документа-родителя (а не строк его табличной части), его не требуется агрегировать. Достаточно включить его в список полей группировки в секции ИТОГИ ПО.

Разберем пример:


ВЫБРАТЬ
    ЗаказКлиента.Ссылка КАК Документ,
    ЗаказКлиента.Проведен КАК Проведен,
    ЗаказКлиентаТовары.Номенклатура КАК Номенклатура
ИЗ
    Документ.ЗаказКлиента КАК ЗаказКлиента
    ЛЕВОЕ СОЕДИНЕНИЕ Документ.ЗаказКлиента.Товары КАК ЗаказКлиентаТовары
        ПО ЗаказКлиента.Ссылка = ЗаказКлиентаТовары.Ссылка

ИТОГИ ПО
    Документ,
    Проведен

Способ 3. Преобразование в число и условные выражения в итогах

Если для родительской строки требуется более сложная логика (например, подсчет флага по условию), можно привести логическое значение к числу (0 или 1) или использовать конструкцию ВЫБОР прямо в секции итогов.

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


ВЫБРАТЬ
    ЗаказКлиентаТовары.Ссылка КАК Документ,
    ЗаказКлиентаТовары.Номенклатура КАК Номенклатура,
    ВЫБОР
        КОГДА ЗаказКлиентаТовары.Отменено ТОГДА 1
        ИНАЧЕ 0
    КОНЕЦ КАК ФлагЧислом
ИЗ
    Документ.ЗаказКлиента.Товары КАК ЗаказКлиентаТовары

ИТОГИ
    СУММА(ФлагЧислом)
ПО
    Документ

Также в секции ИТОГИ допускается использование условного оператора ВЫБОР для получения результирующего булева значения на уровне группы:


ИТОГИ
    МАКСИМУМ(ВЫБОР КОГДА ФлагОтмены ТОГДА 1 ИНАЧЕ 0 КОНЕЦ) = 1 КАК ФлагОтмены
ПО
    Документ

Способ 4. Программная постобработка дерева значений

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

Разберем по шагам логику такого обхода:

  1. Выгружаем результат запроса в дерево значений через Запрос.Выполнить().Выгрузить(ОбходРезультатаЗапроса.ПоГруппировкам).
  2. Выполняем обход коллекции Строки полученного дерева значений.
  3. Проверяем значения флагов у дочерних элементов и устанавливаем результирующее значение в текущую родительскую строку.

Если дерево отображается в управляемой форме, для элементов типа Поле флажка рекомендуется включить свойство ТриСостоянияФлажка, чтобы пользователь мог визуально различать полностью отмеченные, частично отмеченные и не отмеченные группы строк.

← На главную