При разработке сложных отчетов в 1С часто возникает задача собрать данные из разных источников (например, из нескольких видов документов: реализации, поступления, кассовые ордера) с помощью конструкции ОБЪЕДИНИТЬ ВСЕ. Одной из проблем при таком подходе становится организация удобного пользовательского отбора по конкретному типу документа. Нам необходимо, чтобы пользователь мог выбрать один или несколько видов документов, а если отбор не задан — отчет должен выводить все данные без исключения.
В этой статье мы подробно проанализируем ситуацию, разберем технические нюансы и рассмотрим несколько способов решения задачи: от использования стандартных возможностей конструктора СКД до программного управления компоновкой.
Это самый «правильный» и производительный метод с точки зрения платформы 1С. Система компоновки данных (СКД) обладает собственным расширением языка запросов, которое позволяет помечать части запроса (поля, условия, таблицы) специальными фигурными скобками {}. Если пользователь не устанавливает соответствующий отбор в настройках, СКД просто игнорирует текст внутри этих скобок при генерации итогового SQL-запроса.
Рассмотрим, как это применить в нашем случае. Допустим, мы объединяем несколько таблиц во временную таблицу ВТ_Документы. Чтобы дать пользователю возможность фильтровать результат, мы добавим необязательное условие в финальной выборке.
Проанализируем пример кода запроса:
ВЫБРАТЬ
ВТ_Документы.Ссылка КАК Ссылка,
ВТ_Документы.Дата КАК Дата,
ВТ_Документы.Контрагент КАК Контрагент,
ВТ_Документы.СуммаДокумента КАК СуммаДокумента
ИЗ
ВТ_Документы КАК ВТ_Документы
{ГДЕ
(ВЫРАЗИТЬ(ВТ_Документы.Ссылка КАК Документ.РеализацияТоваровУслуг)) КАК ВидДокумента,
(ТИПЗНАЧЕНИЯ(ВТ_Документы.Ссылка)) КАК ТипСсылки}
Почему это работает? Когда вы помещаете условие в фигурные скобки после ключевого слова ГДЕ, СКД понимает, что это поле доступно для отбора. Если в пользовательских настройках на закладке «Отбор» будет выбрано поле Ссылка и указан тип, СКД добавит условие в итоговый запрос. Если отбор пуст — условие ГДЕ вообще не попадет в запрос к базе данных, и мы получим все документы.
Иногда пользователю неудобно выбирать тип через стандартное окно выбора типа ссылки. В таком случае мы можем создать в запросе отдельное поле, которое будет содержать информацию о виде документа, и использовать его для фильтрации.
Разберем по шагам, как это реализовать:
ОБЪЕДИНИТЬ ВСЕ добавим текстовое поле или используем функцию ТИПЗНАЧЕНИЯ.Пример модифицированного запроса:
ВЫБРАТЬ
Реализация.Ссылка КАК Ссылка,
"Реализация товаров" КАК ИмяТипа
ИЗ
Документ.РеализацияТоваровУслуг КАК Реализация
ОБЪЕДИНИТЬ ВСЕ
ВЫБРАТЬ
ПКО.Ссылка,
"Приходный кассовый ордер"
ИЗ
Документ.ПриходныйКассовыйОрдер КАК ПКО
Теперь в настройках компоновки мы можем вынести поле ИмяТипа в «Отбор». Если пользователь выберет «Реализация товаров», отчет автоматически отфильтрует только нужные строки. Однако помните, что сравнение строк работает медленнее, чем сравнение ссылок или типов.
Если количество типов документов невелико и строго фиксировано (как в примере автора темы — 6 документов), можно применить подход с булевыми параметрами. Это позволяет пользователю «включать» или «выключать» целые блоки данных прямо в секции ГДЕ каждой части запроса.
Рассмотрим этот пример подробнее:
ВЫБРАТЬ
РКО.Ссылка,
РКО.Дата,
РКО.СуммаДокумента
ИЗ
Документ.РасходныйКассовыйОрдер КАК РКО
ГДЕ
РКО.Проведен = ИСТИНА
И &ОтбиратьРКО = ИСТИНА
ОБЪЕДИНИТЬ ВСЕ
ВЫБРАТЬ
ППВ.Ссылка,
ППВ.Дата,
ППВ.СуммаДокумента
ИЗ
Документ.ПлатежноеПоручениеВходящее КАК ППВ
ГДЕ
ППВ.Проведен = ИСТИНА
И &ОтбиратьППВ = ИСТИНА
В данном случае нам нужно настроить параметры &ОтбиратьРКО и &ОтбиратьППВ в СКД:
Истина.Если пользователь снимет галочку с параметра &ОтбиратьРКО, соответствующая часть запроса вернет пустой результат, так как условие ЛОЖЬ = ИСТИНА не выполнится.
Если стандартных возможностей конструктора недостаточно (например, нужно динамически менять текст запроса в зависимости от прав доступа или сложных условий), мы можем воспользоваться событием ПриКомпоновкеРезультата в модуле объекта отчета.
Проанализируем ситуацию: нам нужно перехватить настройки, которые установил пользователь, и модифицировать схему. Рассмотрим пример кода для программной установки параметров:
Процедура ПриКомпоновкеРезультата(ДокументРезультат, ДанныеРасшифровки, СтандартнаяОбработка)
СтандартнаяОбработка = Ложь;
// Получаем текущие настройки отчета
Настройки = КомпоновщикНастроек.ПолучитьНастройки();
// Проверяем наличие установленного отбора по полю "Ссылка"
Для Каждого ЭлементОтбора Из Настройки.Отбор.Элементы Цикл
Если ТипЗнч(ЭлементОтбора) = Тип("ЭлементОтбораКомпоновкиДанных")
И ЭлементОтбора.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("Ссылка") Тогда
// Здесь можно выполнить дополнительную логику
КонецЕсли;
КонецЦикла;
// Инициализируем макет и процессор компоновки
КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
МакетКомпоновки = КомпоновщикМакета.Выполнить(СхемаКомпоновкиДанных, Настройки, ДанныеРасшифровки);
ПроцессорКомпоновки = Новый ПроцессорКомпоновкиДанных;
ПроцессорКомпоновки.Инициализировать(МакетКомпоновки, , ДанныеРасшифровки, Истина);
ПроцессорВывода = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВТабличныйДокумент;
ПроцессорВывода.УстановитьДокумент(ДокументРезультат);
ПроцессорВывода.Вывести(ПроцессорКомпоновки);
КонецПроцедуры
При работе с объединением множества таблиц документов (UNION ALL) следует учитывать нагрузку на сервер базы данных. Выясним основные правила оптимизации:
Ссылка ССЫЛКА Документ.РеализацияТоваровУслуг. Это работает быстрее, чем функция ТИПЗНАЧЕНИЯ(), так как платформа 1С более эффективно транслирует оператор ССЫЛКА в SQL-код.Контрагент, Дата), проиндексированы в соответствующих документах.Ссылка, тип которой можно легко фильтровать.Подводя итог, можно сказать, что наиболее универсальным способом является Метод 1 с использованием расширения языка запросов. Он позволяет сохранить гибкость СКД и обеспечивает высокую скорость работы отчета за счет динамического формирования условий запроса на стороне сервера.