Часто перед разработчиками встает задача: реализовать универсальный механизм отбора для любых документов или справочников. Пользователь должен визуально настроить нужные фильтры (как в стандартных отчетах), сохранить эту настройку, а программа затем должна выбрать данные, удовлетворяющие этим условиям, и передать их в обработку. Рассмотрим подробнее, как реализовать подобный функционал, используя механизмы Системы Компоновки Данных (СКД), и разберем классические ошибки, с которыми можно столкнуться при программном формировании результата.
Проанализируем ситуацию: мы программно создаем схему СКД, добавляем в нее запрос, загружаем сохраненные пользовательские настройки, формируем макет и пытаемся вывести результат в ТаблицаЗначений. Исходный код выглядит примерно так:
Схема = Новый СхемаКомпоновкиДанных;
ИсточникДанных = Схема.ИсточникиДанных.Добавить();
ИсточникДанных.ТипИсточникаДанных = "Local";
НаборДанных = Схема.НаборыДанных.Добавить(Тип("НаборДанныхЗапросСхемыКомпоновкиДанных"));
ТекстЗапроса =
"ВЫБРАТЬ
| Справочник1.Ссылка КАК Ссылка
|ИЗ
| Справочник.Справочник1 КАК Справочник1";
НаборДанных.Запрос = ТекстЗапроса;
// Инициализация компоновщика и загрузка сохраненных настроек (СохраненнаяНастройка)
КомпоновщикНастроек = Новый КомпоновщикНастроекКомпоновкиДанных;
Если ЗначениеЗаполнено(СохраненнаяНастройка) Тогда
КомпоновщикНастроек.ЗагрузитьНастройки(СохраненнаяНастройка);
КонецЕсли;
КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
МакетКомпоновки = КомпоновщикМакета.Выполнить(Схема, КомпоновщикНастроек.ПолучитьНастройки(),,, Тип("ГенераторМакетаКомпоновкиДанныхДляКоллекцииЗначений"));
ПроцессорКомпоновки = Новый ПроцессорКомпоновкиДанных;
ПроцессорКомпоновки.Инициализировать(МакетКомпоновки);
ПроцессорВывода = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВКоллекциюЗначений;
ТЗ = Новый ТаблицаЗначений;
ПроцессорВывода.УстановитьОбъект(ТЗ);
ПроцессорВывода.Вывести(ПроцессорКомпоновки);
При выполнении этого кода разработчик сталкивается с проблемой: код отрабатывает без сбоев, но таблица значений остается абсолютно пустой. Выясним причину такого поведения.
В приведенном алгоритме есть несколько критических упущений, характерных для программной работы с СКД. Разберем по шагам, что необходимо исправить:
КомпоновщикНастроек.Настройки.Структура.ТаблицаЗначений. В коллекцию КомпоновщикНастроек.Настройки.Выбор нужно обязательно добавить доступные поля (в нашем случае поле «Ссылка»).ПолеНабораДанныхСхемыКомпоновкиДанных.Часто при наложении сложных отборов результаты выборки могут быть неочевидными. Запрос, который мы видим в конфигураторе (или передаем в переменной), и запрос, который реально отправляется на сервер СУБД после работы компоновщика макета — это разные вещи. Посмотрим на способы получения финального запроса:
1. Программно через отладчик:
Сразу после выполнения метода КомпоновщикМакета.Выполнить() поставьте точку останова. Перейдите в табло и посмотрите значение свойства: МакетКомпоновки.НаборыДанных.НаборДанных1.Запрос (где НаборДанных1 — имя вашего набора). Там вы найдете финальный текст со всеми вшитыми условиями, параметрами и добавленными джоинами.
2. Через «Консоль запросов и отчетов»:
Сохраните сформированную схему в XML. Откройте стандартную консоль в режиме толстого клиента, загрузите туда схему и воспользуйтесь встроенной кнопкой «Анализ исполняемых запросов результата». Это лучший инструмент для отладки условий и параметров СКД.
Чтобы отборы накладывались оптимально и не вызывали деградацию производительности, в тексте исходного запроса следует использовать расширение языка запросов для СКД. Без явного указания платформа попытается наложить условие поверх всей выборки.
Проанализируем пример использования расширения СКД:
ВЫБРАТЬ
Справочник1.Ссылка КАК Ссылка
ИЗ
Справочник.Справочник1 КАК Справочник1
{ГДЕ
Справочник1.Ссылка.*}
Конструкция {ГДЕ ...} дает платформе явное указание, куда именно в SQL-запросе встраивать пользовательские отборы. Особенно это критично при работе с виртуальными таблицами регистров: там отбор обязательно должен пробрасываться внутрь параметров виртуальной таблицы через {ХАРАКТЕРИСТИКИ ...} или параметры таблицы, иначе система сначала вытянет весь регистр, а потом будет фильтровать его в памяти или на уровне временной таблицы.
Если ваша конфигурация написана на управляемых формах, ручное помещение настроек в ХранилищеЗначения является устаревшим подходом. Рассмотрим более эффективные механизмы:
ХранилищеСистемныхНастроек или ХранилищеНастроекДанныхФормы. Платформа 1С:Предприятие 8.3 умеет сохранять пользовательские настройки (в том числе отборы СКД) автоматически при закрытии формы и прозрачно восстанавливать их при открытии.ДинамическийСписок. У него «под капотом» работает свой КомпоновщикНастроекПользовательский, который сам формирует отборы, применяет условное оформление и поддерживает сохранение пользовательских вариантов без написания сложного кода процессора вывода.Важное замечание: При использовании объекта ПроцессорВыводаРезультатаКомпоновкиДанныхВКоллекциюЗначений полностью игнорируется любое условное оформление (выделение цветом, шрифты, формат). Если ваша цель — получить только «сухие» данные (ссылки) для дальнейшей пакетной обработки, этот метод идеален. Но если вы планировали вывести эту таблицу пользователю на экран в красивом виде, лучше использовать процессор вывода в табличный документ или динамический список.