Коллеги, сегодня мы с вами разберем непростую, но весьма распространенную задачу, с которой сталкиваются разработчики при работе со сложными отчетами на Системе Компоновки Данных (СКД) в 1С. Речь пойдет о поведении необязательных параметров во вложенных схемах компоновки данных. Часто возникает ситуация, когда мы хотим, чтобы параметр был необязательным не только в основной схеме, но и во всех вложенных схемах, куда он передается. Однако, стандартные механизмы могут не всегда работать так, как мы ожидаем, и отключенный параметр основной схемы все равно может приводить к нежелательной фильтрации или ошибкам во вложенных схемах.
Представим, что у нас есть отчет СКД, который использует несколько вложенных схем (наборов данных типа "Запрос" или "Объект"). В основной схеме и во вложенных схемах имеются параметры, например, "Период" и "Фирма", которые мы хотим сделать необязательными. Для этого мы обычно используем расширение языка запросов СКД – обрамляем условия с параметрами в фигурные скобки, например: {ГДЕ Таблица.Дата >= &ПериодНачало И Таблица.Дата <= &ПериодКонец}. Это позволяет СКД динамически включать или исключать условие из запроса в зависимости от того, заполнено значение параметра или нет.
Далее, мы связываем параметры вложенных схем с параметрами основной схемы. Делается это в настройках вложенной схемы, где для параметра вложенной схемы в поле "Значение" мы указываем ссылку на параметр владельца, например, ОбъектНастройкиВладелец.ПараметрыДанных.Период.
Но вот где кроется проблема: мы ожидаем, что если пользователь в форме отчета снимет галочку "Использование" для параметра "Период" в основной схеме, то этот параметр будет полностью проигнорирован. Однако, на практике во вложенные схемы может передаваться значение Null, и, что самое важное, флаг "Использование" для соответствующего параметра *во вложенной схеме* почему-то остается установленным в Истина. В результате, запрос во вложенной схеме пытается отфильтровать данные по NULL, что может привести к следующим последствиям:
NULL или имеет строгую проверку типа.Таким образом, простого использования фигурных скобок в запросе и связывания параметров через ОбъектНастройкиВладелец.ПараметрыДанных оказывается недостаточно для обеспечения истинной необязательности параметров во вложенных схемах.
Для того чтобы добиться желаемого поведения, когда отключенный в основной схеме параметр полностью игнорируется и во вложенных схемах, нам потребуется применить программное управление настройками СКД. Мы будем перехватывать процесс компоновки результата в процедуре-обработчике ПриКомпоновкеРезультата и вручную отключать использование соответствующих параметров во вложенных схемах, если родительский параметр не используется.
Разберем по шагам, как это реализовать:
ПриКомпоновкеРезультата мы устанавливаем флаг СтандартнаяОбработка = Ложь. Это означает, что мы берем на себя полный контроль над процессом формирования отчета, от макета компоновки до вывода результата.КомпоновщикНастроек.ПолучитьНастройки(). Эти настройки включают в себя параметры, отборы, поля, структуру отчета и другие аспекты.Использование. Если оно установлено в Ложь (то есть, пользователь отключил параметр), то нам необходимо предпринять дальнейшие действия.НастройкиВложенногоОбъектаКомпоновкиДанных. Мы проходим циклом по коллекции Настройки.Структура, чтобы найти все вложенные схемы.Использование = Ложь. Это гарантирует, что даже если во вложенную схему передается Null, само условие с этим параметром будет полностью исключено из запроса, поскольку его использование отключено.Давайте посмотрим на пример кода для обработчика ПриКомпоновкеРезультата, который реализует описанный подход:
Процедура ПриКомпоновкеРезультата(ДокументРезультат, ДанныеРасшифровки, СтандартнаяОбработка)
// Отменяем стандартную обработку, чтобы вручную управлять компоновкой
СтандартнаяОбработка = Ложь;
// Получаем текущие настройки отчета из компоновщика настроек
Настройки = КомпоновщикНастроек.ПолучитьНастройки();
// Определяем имя параметра, который мы хотим контролировать
// Замените "ВашПараметр" на фактическое имя параметра в вашей схеме СКД (например, "Период" или "Фирма")
ИмяПараметраДляКонтроля = "ВашПараметр";
// Проверяем, отключен ли основной параметр в настройках верхнего уровня
ПараметрВерхнегоУровня = Настройки.ПараметрыДанных.НайтиЗначениеПараметра(Новый ПараметрКомпоновкиДанных(ИмяПараметраДляКонтроля));
Если ПараметрВерхнегоУровня <> Неопределено Тогда
Если ПараметрВерхнегоУровня.Использование = Ложь Тогда
// Если основной параметр отключен, то ищем его во всех вложенных схемах
// и отключаем там тоже.
Для Каждого ЭлементСтруктуры Из Настройки.Структура Цикл
// Проверяем, является ли элемент структуры вложенной схемой
Если ТипЗнч(ЭлементСтруктуры) = Тип("НастройкиВложенногоОбъектаКомпоновкиДанных") Тогда
// Получаем параметр из настроек текущей вложенной схемы
ПараметрВложеннойСхемы = ЭлементСтруктуры.Настройки.ПараметрыДанных.НайтиЗначениеПараметра(Новый ПараметрКомпоновкиДанных(ИмяПараметраДляКонтроля));
Если ПараметрВложеннойСхемы <> Неопределено Тогда
// Если параметр найден во вложенной схеме, отключаем его использование
ПараметрВложеннойСхемы.Использование = Ложь;
КонецЕсли;
КонецЕсли;
КонецЦикла;
КонецЕсли;
КонецЕсли;
// После всех корректировок настроек выполняем ручную компоновку макета
КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
МакетКомпоновки = КомпоновщикМакета.Выполнить(СхемаКомпоновкиДанных, Настройки, ДанныеРасшифровки, , , Ложь);
// Инициализируем процессор компоновки данных
ПроцессорКомпоновки = Новый ПроцессорКомпоновкиДанных;
ПроцессорКомпоновки.Инициализировать(МакетКомпоновки,, ДанныеРасшифровки, Истина);
// Инициализируем процессор вывода результата в табличный документ
ПроцессорВывода = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВТабличныйДокумент;
ПроцессорВывода.УстановитьДокумент(ДокументРезультат);
// Выводим результат компоновки в табличный документ
ПроцессорВывода.Вывести(ПроцессорКомпоновки);
КонецПроцедуры
Примечание по параметру КлючВарианта: В исходном сообщении с форума присутствовало условие Если Настройки.ДополнительныеСвойства.КлючВарианта = "ПолевыеДубликаты" Тогда. Это условие, скорее всего, специфично для конкретного варианта отчета или конфигурации автора и не является обязательным для общего решения проблемы. В нашем примере кода мы его опустили для универсальности, но вы можете включить его, если вам требуется применять это решение только для определенных вариантов отчета.
Настройки.Структура и проверкой типа НастройкиВложенногоОбъектаКомпоновкиДанных является гораздо более надежным, чем обращение по индексам (например, Настройки.Структура[1]), так как индексы могут меняться при изменении структуры отчета.Новый ПараметрКомпоновкиДанных(ИмяПараметраДляКонтроля), точно соответствует именам параметров как в основной схеме, так и во вложенных схемах. Регистр символов имеет значение.СтандартнаяОбработка = Ложь обязывает вас полностью управлять всеми этапами формирования отчета: от создания макета до вывода. Если вы не выполните все необходимые шаги, отчет не будет сформирован.Настройки, ЭлементСтруктуры, ПараметрВерхнегоУровня и ПараметрВложеннойСхемы, а также их свойства Использование. Это поможет локализовать источник некорректного поведения.Таким образом, программное вмешательство в настройки СКД через обработчик ПриКомпоновкеРезультата предоставляет нам мощный инструмент для решения тонких проблем, связанных с передачей и обработкой параметров, особенно во вложенных схемах. Этот метод позволяет нам обеспечить, чтобы необязательные параметры действительно вели себя как необязательные, полностью исключаясь из процесса фильтрации, когда это необходимо.