Как корректно отключить необязательные параметры во вложенных схемах СКД, если они передаются как ОбъектНастройкиВладелец.ПараметрыДанных?

Программист 1С v8.3 (Управляемые формы)
← На главную

Коллеги, сегодня мы с вами разберем непростую, но весьма распространенную задачу, с которой сталкиваются разработчики при работе со сложными отчетами на Системе Компоновки Данных (СКД) в 1С. Речь пойдет о поведении необязательных параметров во вложенных схемах компоновки данных. Часто возникает ситуация, когда мы хотим, чтобы параметр был необязательным не только в основной схеме, но и во всех вложенных схемах, куда он передается. Однако, стандартные механизмы могут не всегда работать так, как мы ожидаем, и отключенный параметр основной схемы все равно может приводить к нежелательной фильтрации или ошибкам во вложенных схемах.

Суть проблемы: Некорректное поведение необязательных параметров во вложенных схемах

Представим, что у нас есть отчет СКД, который использует несколько вложенных схем (наборов данных типа "Запрос" или "Объект"). В основной схеме и во вложенных схемах имеются параметры, например, "Период" и "Фирма", которые мы хотим сделать необязательными. Для этого мы обычно используем расширение языка запросов СКД – обрамляем условия с параметрами в фигурные скобки, например: {ГДЕ Таблица.Дата >= &ПериодНачало И Таблица.Дата <= &ПериодКонец}. Это позволяет СКД динамически включать или исключать условие из запроса в зависимости от того, заполнено значение параметра или нет.

Далее, мы связываем параметры вложенных схем с параметрами основной схемы. Делается это в настройках вложенной схемы, где для параметра вложенной схемы в поле "Значение" мы указываем ссылку на параметр владельца, например, ОбъектНастройкиВладелец.ПараметрыДанных.Период.

Но вот где кроется проблема: мы ожидаем, что если пользователь в форме отчета снимет галочку "Использование" для параметра "Период" в основной схеме, то этот параметр будет полностью проигнорирован. Однако, на практике во вложенные схемы может передаваться значение Null, и, что самое важное, флаг "Использование" для соответствующего параметра *во вложенной схеме* почему-то остается установленным в Истина. В результате, запрос во вложенной схеме пытается отфильтровать данные по NULL, что может привести к следующим последствиям:

  1. Ошибки выполнения запроса, если поле, по которому идет фильтрация, не допускает сравнения с NULL или имеет строгую проверку типа.
  2. Некорректная фильтрация данных, когда вместо полного отсутствия фильтра мы получаем фильтр по отсутствующим значениям, что часто не соответствует требуемому поведению.
  3. Нежелательное поведение, при котором отчет возвращает пустые данные или данные, не соответствующие ожиданиям пользователя.

Таким образом, простого использования фигурных скобок в запросе и связывания параметров через ОбъектНастройкиВладелец.ПараметрыДанных оказывается недостаточно для обеспечения истинной необязательности параметров во вложенных схемах.

Решение: Программное управление параметрами вложенных схем в ПриКомпоновкеРезультата

Для того чтобы добиться желаемого поведения, когда отключенный в основной схеме параметр полностью игнорируется и во вложенных схемах, нам потребуется применить программное управление настройками СКД. Мы будем перехватывать процесс компоновки результата в процедуре-обработчике ПриКомпоновкеРезультата и вручную отключать использование соответствующих параметров во вложенных схемах, если родительский параметр не используется.

Разберем по шагам, как это реализовать:

  1. Отменяем стандартную обработку: Первым делом в процедуре ПриКомпоновкеРезультата мы устанавливаем флаг СтандартнаяОбработка = Ложь. Это означает, что мы берем на себя полный контроль над процессом формирования отчета, от макета компоновки до вывода результата.
  2. Получаем текущие настройки компоновщика: Мы получаем текущие настройки отчета, которые были заданы пользователем в форме отчета, с помощью метода КомпоновщикНастроек.ПолучитьНастройки(). Эти настройки включают в себя параметры, отборы, поля, структуру отчета и другие аспекты.
  3. Проверяем состояние основного параметра: Мы находим наш "проблемный" параметр (например, "ВашПараметр") в параметрах данных основной схемы и проверяем его свойство Использование. Если оно установлено в Ложь (то есть, пользователь отключил параметр), то нам необходимо предпринять дальнейшие действия.
  4. Итерируем по структуре отчета для поиска вложенных схем: Настройки отчета представляют собой иерархическую структуру. Вложенные схемы являются элементами этой структуры и имеют тип НастройкиВложенногоОбъектаКомпоновкиДанных. Мы проходим циклом по коллекции Настройки.Структура, чтобы найти все вложенные схемы.
  5. Отключаем параметр во вложенных схемах: Для каждой найденной вложенной схемы мы получаем ее собственные настройки, а затем в этих настройках находим тот же параметр ("ВашПараметр") и явно устанавливаем его свойство Использование = Ложь. Это гарантирует, что даже если во вложенную схему передается Null, само условие с этим параметром будет полностью исключено из запроса, поскольку его использование отключено.
  6. Выполняем ручную компоновку и вывод: После того как мы скорректировали настройки вложенных схем, нам необходимо вручную запустить процесс компоновки макета, обработки компоновки и вывода результата в табличный документ, поскольку стандартная обработка была нами отключена.

Давайте посмотрим на пример кода для обработчика ПриКомпоновкеРезультата, который реализует описанный подход:

Пример кода для программного отключения параметров


Процедура ПриКомпоновкеРезультата(ДокументРезультат, ДанныеРасшифровки, СтандартнаяОбработка)
    // Отменяем стандартную обработку, чтобы вручную управлять компоновкой
    СтандартнаяОбработка = Ложь;

    // Получаем текущие настройки отчета из компоновщика настроек
    Настройки = КомпоновщикНастроек.ПолучитьНастройки();

    // Определяем имя параметра, который мы хотим контролировать
    // Замените "ВашПараметр" на фактическое имя параметра в вашей схеме СКД (например, "Период" или "Фирма")
    ИмяПараметраДляКонтроля = "ВашПараметр"; 

    // Проверяем, отключен ли основной параметр в настройках верхнего уровня
    ПараметрВерхнегоУровня = Настройки.ПараметрыДанных.НайтиЗначениеПараметра(Новый ПараметрКомпоновкиДанных(ИмяПараметраДляКонтроля));

    Если ПараметрВерхнегоУровня <> Неопределено Тогда
        Если ПараметрВерхнегоУровня.Использование = Ложь Тогда
            // Если основной параметр отключен, то ищем его во всех вложенных схемах
            // и отключаем там тоже.
            Для Каждого ЭлементСтруктуры Из Настройки.Структура Цикл
                // Проверяем, является ли элемент структуры вложенной схемой
                Если ТипЗнч(ЭлементСтруктуры) = Тип("НастройкиВложенногоОбъектаКомпоновкиДанных") Тогда
                    // Получаем параметр из настроек текущей вложенной схемы
                    ПараметрВложеннойСхемы = ЭлементСтруктуры.Настройки.ПараметрыДанных.НайтиЗначениеПараметра(Новый ПараметрКомпоновкиДанных(ИмяПараметраДляКонтроля));
                    
                    Если ПараметрВложеннойСхемы <> Неопределено Тогда
                        // Если параметр найден во вложенной схеме, отключаем его использование
                        ПараметрВложеннойСхемы.Использование = Ложь;
                    КонецЕсли;
                КонецЕсли;
            КонецЦикла;
        КонецЕсли;
    КонецЕсли;
    
    // После всех корректировок настроек выполняем ручную компоновку макета
    КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
    МакетКомпоновки = КомпоновщикМакета.Выполнить(СхемаКомпоновкиДанных, Настройки, ДанныеРасшифровки, , , Ложь);

    // Инициализируем процессор компоновки данных
    ПроцессорКомпоновки = Новый ПроцессорКомпоновкиДанных;
    ПроцессорКомпоновки.Инициализировать(МакетКомпоновки,, ДанныеРасшифровки, Истина);

    // Инициализируем процессор вывода результата в табличный документ
    ПроцессорВывода = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВТабличныйДокумент;
    ПроцессорВывода.УстановитьДокумент(ДокументРезультат);

    // Выводим результат компоновки в табличный документ
    ПроцессорВывода.Вывести(ПроцессорКомпоновки);
КонецПроцедуры

Примечание по параметру КлючВарианта: В исходном сообщении с форума присутствовало условие Если Настройки.ДополнительныеСвойства.КлючВарианта = "ПолевыеДубликаты" Тогда. Это условие, скорее всего, специфично для конкретного варианта отчета или конфигурации автора и не является обязательным для общего решения проблемы. В нашем примере кода мы его опустили для универсальности, но вы можете включить его, если вам требуется применять это решение только для определенных вариантов отчета.

Важные моменты и рекомендации

  1. Универсальность и надежность: Подход с итерацией по Настройки.Структура и проверкой типа НастройкиВложенногоОбъектаКомпоновкиДанных является гораздо более надежным, чем обращение по индексам (например, Настройки.Структура[1]), так как индексы могут меняться при изменении структуры отчета.
  2. Имя параметра: Убедитесь, что имя параметра, используемое в Новый ПараметрКомпоновкиДанных(ИмяПараметраДляКонтроля), точно соответствует именам параметров как в основной схеме, так и во вложенных схемах. Регистр символов имеет значение.
  3. Полный контроль над компоновкой: Помните, что установка СтандартнаяОбработка = Ложь обязывает вас полностью управлять всеми этапами формирования отчета: от создания макета до вывода. Если вы не выполните все необходимые шаги, отчет не будет сформирован.
  4. Отладка: При возникновении проблем используйте отладчик 1С, чтобы пошагово просмотреть выполнение кода, проверить значения переменных Настройки, ЭлементСтруктуры, ПараметрВерхнегоУровня и ПараметрВложеннойСхемы, а также их свойства Использование. Это поможет локализовать источник некорректного поведения.

Таким образом, программное вмешательство в настройки СКД через обработчик ПриКомпоновкеРезультата предоставляет нам мощный инструмент для решения тонких проблем, связанных с передачей и обработкой параметров, особенно во вложенных схемах. Этот метод позволяет нам обеспечить, чтобы необязательные параметры действительно вели себя как необязательные, полностью исключаясь из процесса фильтрации, когда это необходимо.

← На главную