Работа с Системой компоновки данных (СКД) часто преподносит сюрпризы, особенно когда отчет строится на основе нескольких наборов данных или использует внешние источники (например, таблицы MS SQL Server). Одной из самых коварных проблем является ситуация, когда стандартный отбор по значению "Не заполнено", "Пустая ссылка" или "NULL" просто игнорируется системой. При этом визуально в отчете мы видим пустые поля, а условное оформление для этих же полей отрабатывает корректно.
В этой статье мы подробно разберем, почему так происходит, и изучим пошаговые инструкции по решению данной проблемы. Мы проанализируем механизмы работы компоновщика макета и выясним, как заставить фильтры работать правильно.
Рассмотрим ситуацию, когда в отчете используются два набора данных — запрос к базе 1С и запрос к внешней таблице SQL. Когда мы устанавливаем отбор на закладке "Настройки" — "Отбор", СКД пытается применить этот фильтр максимально эффективно. Она старается "пробросить" условие ГДЕ непосредственно в текст SQL-запроса каждого набора данных еще до того, как данные будут получены в память 1С.
Проанализируем проблему: если поле, по которому идет отбор, принадлежит второму набору данных, а связь между наборами выполняется по принципу ЛЕВОЕ СОЕДИНЕНИЕ, то в итоговом результате могут появиться значения NULL для тех строк, которым не нашлось соответствия. Однако на этапе выполнения первичного запроса второго набора данных система еще "не знает" о результате связи. В итоге глобальный отбор может отсекать данные некорректно или полностью игнорироваться.
Решение: Перенос отбора на уровень группировки.
ЗаказПоставщику), внутри которой должны фильтроваться данные.Таким образом, СКД сначала получит данные из всех источников, выполнит их соединение в памяти, и только после этого применит фильтр к уже сформированной таблице. Это гарантирует, что значения NULL или ПустаяСсылка будут корректно обработаны компоновщиком.
При работе с внешними источниками через ODBC или прямой запрос к MS SQL часто возникает конфликт типов. В 1С ПустаяСсылка — это специфический объект, а в SQL пустое значение — это чаще всего NULL. Кроме того, строковые поля в SQL могут иметь тип char с фиксированной длиной, и тогда "пустая" строка на самом деле будет заполнена пробелами.
Выясним причину через использование вычисляемых полей. Если стандартный отбор "Не заполнено" не видит пустое значение, попробуем нормализовать данные. Создадим вычисляемое поле, которое будет возвращать строковый маркер:
Выбор
Когда ИмяПоля ЕСТЬ NULL Тогда "ПУСТО"
Когда ИмяПоля = "" Тогда "ПУСТО"
Иначе "ЗАПОЛНЕНО"
Конец
Теперь мы можем установить отбор по этому вычисляемому полю со значением Равно "ПУСТО". Этот метод работает безотказно, так как вычисляемые поля обрабатываются на финальном этапе компоновки результата.
Рассмотрим ситуацию, описанную во втором случае, когда используются необязательные параметры в фигурных скобках. Часто программисты пишут условие следующим образом:
ВЫБРАТЬ
Поступление.Ссылка КАК Ссылка,
Поступление.А_ЦФО КАК ЦФО
ИЗ
Документ.ПоступлениеТоваровУслуг КАК Поступление
{ГДЕ
(Поступление.А_ЦФО = &ЦФО)}
Проанализируем поведение системы: если параметр &ЦФО имеет тип Строка и он не заполнен (пустая строка), СКД может решить, что условие задавать не нужно, и полностью исключит секцию ГДЕ из итогового запроса. В результате отчет выведет все данные, игнорируя попытку пользователя отобрать "пустые" значения.
Чтобы строковый параметр отрабатывал корректно как фильтр "по пустому", рекомендуется использовать стандартные поля отбора вместо параметров в фигурных скобках или явно проверять заполненность в самом запросе:
ГДЕ
(&ОтбиратьПустые = ИСТИНА И Поступление.А_ЦФО = "")
ИЛИ (Поступление.А_ЦФО = &ЦФО)
Если решение не очевидно, крайне важно посмотреть на исполняемый запрос. Исходный текст запроса в конфигураторе и то, что 1С реально отправляет в СУБД — это разные вещи.
Посмотрим на алгоритм отладки:
WHERE (ГДЕ). Если вы видите там условие 1=1 или отсутствие вашего поля, значит, СКД исключила отбор на этапе оптимизации.Часто в консоли можно заметить, что СКД пытается сравнить Guid из SQL со строкой 1С, что приводит к пустому результату. В этом случае поможет явное приведение типов в запросе набора данных через ВЫРАЗИТЬ(Поле КАК Тип).
Это самый важный диагностический момент. Условное оформление (например, покраска строки в красный цвет, если поле пустое) выполняется процессором вывода в самом конце. На этом этапе данные уже превратились в объекты 1С (строки, числа, ссылки). Отбор же работает на этапе генерации макета. Если логика связи наборов данных мешает системе однозначно определить значение поля до момента компоновки, отбор будет проигнорирован. Именно поэтому перенос фильтра в настройки группировки — самое простое и эффективное решение, так как это заставляет систему выполнять фильтрацию на том же этапе, на котором работает условное оформление.
Разберем еще один нюанс: использование функции ЕстьNull(). В запросах СКД, объединяющих несколько наборов, рекомендуется всегда оборачивать потенциально пустые поля из правых таблиц соединений:
ВЫБРАТЬ
Заказ.Ссылка КАК Заказ,
ЕстьNull(ВнешнийИсточник.ID, 0) КАК Идентификатор
ИЗ
Заказы КАК Заказ
Это позволит избежать неопределенности при наложении стандартных фильтров компоновки данных.