При работе с конфигурациями на базе БСП (Библиотека стандартных подсистем), такими как 1С:Комплексная автоматизация 2.4, 1С:ERP или 1С:Управление торговлей 11, разработчики и аналитики часто сталкиваются с проблемой фильтрации данных по дополнительным реквизитам. Особенно остро эта проблема проявляется для реквизитов с типом Булево. В отчетах, построенных на системе компоновки данных (СКД), значения «Да» (Истина) отображаются и фильтруются корректно, а вот значения «Нет» (Ложь) часто выглядят как пустые поля, и отбор по ним не срабатывает.
В данной статье мы подробно разберем, почему так происходит, как устроен механизм генерации запросов в БСП и какими способами можно обеспечить корректную работу отчетов для пользователей.
Для начала проанализируем внутреннее устройство хранения данных. В БСП реализована оптимизация дискового пространства. Для дополнительных реквизитов типа Булево запись в табличную часть ДополнительныеРеквизиты объекта (справочника или документа) создается только в том случае, если значение установлено в Истина. Если же значение реквизита равно Ложь, строка из табличной части просто удаляется (или не создается вовсе).
Когда система компоновки данных (СКД) строит отчет, она использует механизм Характеристик. В запросе это превращается в ЛЕВОЕ СОЕДИНЕНИЕ (LEFT JOIN) основной таблицы документа с таблицей дополнительных реквизитов. Рассмотрим, что происходит на уровне SQL-запроса:
Истина.NULL.Проблема заключается в том, что в стандартных настройках отбора пользователь выбирает Равно — Нет. Однако с точки зрения базы данных NULL не равен Ложь. Математически сравнение NULL = Ложь дает результат «Неизвестно» (Unknown), и такие строки отсекаются фильтром. Именно поэтому отчет по «ненапечатанным» документам или документам со значением «Нет» может выходить пустым.
Самый простой способ, не требующий изменения кода конфигурации, — это использование встроенных возможностей интерфейса СКД. Рассмотрим, как это сделать по шагам:
Равно и Не равно, необходимо перейти в расширенный режим. Для этого нажмем кнопку Еще — Прочее — Изменить вариант отчета.Не заполнено.Поскольку физически значения Ложь в базе нет (там NULL), условие Не заполнено корректно выберет все документы, где данный флаг не установлен в значение Истина.
Если нам нужно более гибкое условие (например, учитывать и старые записи, где Ложь могла быть записана физически, и новые, где стоит NULL), мы можем сгруппировать условия. Проанализируем ситуацию: нам подходят строки, где значение либо реально равно Ложь, либо не задано вовсе.
Для этого в настройках отбора выполним следующие действия:
ДопРеквизит Равно ЛожьДопРеквизит Не заполненоТакой подход гарантирует, что в выборку попадут все нужные документы вне зависимости от версии БСП и способа записи данных.
Если мы разрабатываем собственный отчет или имеем возможность изменить существующий через расширение, мы можем решить проблему на уровне схемы компоновки данных. Рассмотрим вариант с использованием Вычисляемых полей.
Выясним причину: нам нужно, чтобы СКД видела Ложь вместо NULL. Для этого:
Напечатано_ДляОтбора.
ЕСТЬNULL(ДополнительныйРеквизит_Напечатано, Ложь)
Булево и никогда не будет NULL.Механизм характеристик в БСП и платформе работает автоматически. Платформа видит описание в метаданных или в тексте запроса через конструкцию ХАРАКТЕРИСТИКИ. Вмешаться в саму генерацию LEFT JOIN платформой напрямую сложно, но можно повлиять на описание характеристик.
В БСП за формирование описания характеристик отвечают общие модули, такие как УправлениеСвойствами и ОбщегоНазначенияБСП. В частности, стоит обратить внимание на функцию, которая возвращает текст запроса для получения значений свойств. Если изменить описание источника характеристик на вложенный запрос с ЕСТЬNULL, проблема исчезнет глобально для всех отчетов.
Пример программного изменения настроек компоновки перед выводом:
Процедура ПриКомпоновкеРезультата(ДокументРезультат, ДанныеРасшифровки, СтандартнаяОбработка)
// Получаем текущие настройки отчета
Настройки = КомпоновщикНастроек.ПолучитьНастройки();
// Пройдемся по отборам и модифицируем условия по булевым доп. реквизитам
Для Каждого ЭлементОтбора Из Настройки.Отбор.Элементы Цикл
Если ТипЗнч(ЭлементОтбора) = Тип("ЭлементОтбораКомпоновкиДанных") Тогда
// Логика поиска нужного поля и замены вида сравнения
// на группу ИЛИ (Ложь + Не заполнено)
КонецЕсли;
КонецЦикла;
// Устанавливаем измененные настройки обратно
КомпоновщикНастроек.ЗагрузитьНастройки(Настройки);
КонецПроцедуры
Проанализируем ситуацию с другими типами данных. Для типов Число и Строка проблема стоит не так остро. Как правило, БСП записывает 0 или Пустую строку в табличную часть, если пользователь явно взаимодействовал с полем в форме объекта. Однако, если запись была создана программно без заполнения этих реквизитов, в отчетах также возникнет NULL.
Важный совет: При разработке систем, активно использующих дополнительные реквизиты для бизнес-логики, старайтесь всегда проверять поля на Заполнено / Не заполнено в отчетах. Это самый надежный способ, учитывающий оптимизированное хранение данных в 1С.
Мы выяснили, что отсутствие значений «Нет» в отчетах — это не ошибка, а следствие оптимизации хранения данных в БСП. Для решения задачи можно:
ЕСТЬNULL на уровне СКД.ПриКомпоновкеРезультата.Выбор метода зависит от того, есть ли у вас доступ к изменению конфигурации и насколько массово требуется решить данную проблему в информационной базе.