Как расшифровать отчет СКД другим вариантом, программно устанавливая отборы, и избежать ошибки "невозможно применить фиксированные настройки"?

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

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

Понимание природы ошибки "невозможно применить фиксированные настройки. совпадают значения параметра"

Для начала, давайте выясним причину возникновения этой ошибки. В СКД существуют различные типы настроек, которые могут влиять на формирование отчета:

  1. Стандартные настройки: Задаются разработчиком в конфигураторе для основного варианта отчета.
  2. Пользовательские настройки: Изменяются и сохраняются пользователем в режиме 1С:Предприятие. Они имеют приоритет над стандартными.
  3. Фиксированные настройки: Устанавливаются программно и предназначены для тех случаев, когда определенные параметры или отборы не должны изменяться пользователем.

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

Рассмотрим пример кода, который приводит к этой ошибке:


ПараметрыФормы = Новый Структура;
ПараметрыФормы.Вставить("СформироватьПриОткрытии", Истина);
ПараметрыФормы.Вставить("КлючВарианта", "Расшифровка"); // Вариант отчета, возможно, имеет свои настройки
СтруктураОтбора = Новый Структура;
СтруктураОтбора.Вставить("ПериодДоставки", Период);
СтруктураОтбора.Вставить("ДатаНачала", Период.ДатаНачала);
СтруктураОтбора.Вставить("ДатаОкончания", Период.ДатаОкончания);
ПараметрыФормы.Вставить("Отбор", СтруктураОтбора); // Здесь мы пытаемся передать отбор как фиксированный параметр
ФормаРасшифровки = ПолучитьФорму(ИмяОтчета+".Форма", ПараметрыФормы, , Истина);

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

Также проблема усугубляется, если в модуле объекта отчета присутствует процедура ПриКомпоновкеРезультата, где мы вручную управляем настройками компоновщика:


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

Вызов КомпоновщикНастроек.ПолучитьНастройки() приводит к объединению всех типов настроек (стандартных, пользовательских, фиксированных), и именно в этот момент проявляется конфликт.

Основное решение: передача параметров через пользовательские настройки

Чтобы избежать ошибки с фиксированными настройками, нам следует передавать динамические отборы и параметры для расшифровки не как фиксированные настройки формы, а как пользовательские настройки отчета, который мы открываем.

Мы будем открывать форму отчета, а затем, после её получения, программно изменять пользовательские настройки компоновщика в этой форме.

  1. Получаем форму отчета расшифровки: Сначала получаем форму отчета, но без передачи конфликтующих отборов через ПараметрыФормы. Можно передать только КлючВарианта и флаг СформироватьПриОткрытии.
  2. Добираемся до настроек компоновщика: После получения формы, мы можем обратиться к объекту отчета, находящемуся в ней, и получить доступ к его компоновщику настроек.
  3. Устанавливаем параметры/отборы в пользовательские настройки: Мы либо находим существующие элементы отбора/параметра в коллекции пользовательских настроек и меняем их значения, либо добавляем новые элементы отбора, если их там нет.

Вот как мы можем переделать наш исходный код:


// Шаг 1: Подготавливаем базовые параметры для открытия формы
ПараметрыФормы = Новый Структура;
ПараметрыФормы.Вставить("СформироватьПриОткрытии", Истина);
ПараметрыФормы.Вставить("КлючВарианта", "Расшифровка");

// Шаг 2: Получаем форму отчета расшифровки
// Важно: не передаем сюда параметр "Отбор", чтобы избежать конфликта с фиксированными настройками
ФормаРасшифровки = ПолучитьФорму(ИмяОтчета+".Форма", ПараметрыФормы, , Истина);

// Шаг 3: Добираемся до настроек компоновщика отчета внутри формы
// Объект формы содержит поле "Отчет", которое является объектом отчета
// Объект отчета содержит КомпоновщикНастроек
КомпоновщикНастроекРасшифровки = ФормаРасшифровки.Отчет.КомпоновщикНастроек;

// Шаг 4: Теперь мы можем работать с настройками компоновщика.
// Если нужно изменить ПараметрыДанных, то обращаемся к КомпоновщикНастроекРасшифровки.Настройки.ПараметрыДанных
// Если нужно изменить Отборы, то обращаемся к КомпоновщикНастроекРасшифровки.Настройки.Отбор
// Передаем значения Период, ДатаНачала, ДатаОкончания
// Важно: ищем элементы в основных настройках (которые объединяют пользовательские и стандартные),
// а не только в ПользовательскиеНастройки.Элементы, так как отбор может быть задан в варианте по умолчанию.

// Пример установки параметров (если они есть в схеме компоновки данных как параметры):
Для Каждого ЭлементПараметра Из КомпоновщикНастроекРасшифровки.Настройки.ПараметрыДанных Цикл
    Если ЭлементПараметра.Имя = "ПериодДоставки" Тогда
        ЭлементПараметра.Значение = Период;
        ЭлементПараметра.Использование = Истина;
    ИначеЕсли ЭлементПараметра.Имя = "ДатаНачала" Тогда
        ЭлементПараметра.Значение = Период.ДатаНачала;
        ЭлементПараметра.Использование = Истина;
    ИначеЕсли ЭлементПараметра.Имя = "ДатаОкончания" Тогда
        ЭлементПараметра.Значение = Период.ДатаОкончания;
        ЭлементПараметра.Использование = Истина;
    КонецЕсли;
КонецЦикла;

// Если нам нужно программно установить отборы, то это делается следующим образом (см. следующий раздел)

// Открываем форму
ФормаРасшифровки.Открыть();

Таким образом, мы избегаем прямого конфликта, поскольку не пытаемся применить "фиксированные" настройки формы. Вместо этого мы манипулируем объектом КомпоновщикНастроек уже открытой (но ещё не показанной пользователю) формы отчета.

Передача значений группировок как элементы отбора для отчета расшифровки

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

В этом случае нам нужно будет программно добавить или изменить элементы отбора в коллекции Настройки.Отбор.Элементы объекта КомпоновщикНастроек в форме расшифровки.

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

Разберем шаги:

  1. Получаем объект Настройки компоновщика отчета расшифровки.
  2. Перебираем структуру с данными расшифровки (СтруктураДанных.ЗначенияГруппировок), где ключ — это имя поля группировки, а значение — это её значение.
  3. Для каждого поля группировки пытаемся найти соответствующий элемент отбора в Настройки.Отбор.Элементы.
  4. Если элемент отбора найден, мы обновляем его значение.
  5. Если элемент отбора не найден, мы программно создаем новый ЭлементОтбораКомпоновкиДанных и добавляем его в коллекцию.

Вот пример кода, демонстрирующий этот подход:


// ... код получения ФормаРасшифровки, как показано выше ...

КомпоновщикНастроекРасшифровки = ФормаРасшифровки.Отчет.КомпоновщикНастроек;
Настройки = КомпоновщикНастроекРасшифровки.Настройки;

// СтруктураДанных.ЗначенияГруппировок - это структура,
// которую мы обычно получаем при расшифровке отчета,
// где ключ - имя поля, значение - его значение.
// Например: СтруктураДанных.ЗначенияГруппировок = Новый Структура("Номенклатура", МояНоменклатура, "Склад", МойСклад);

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

// Теперь, когда все отборы установлены, можно открыть форму
ФормаРасшифровки.Открыть();

Этот подход позволяет нам гибко управлять отборами, независимо от того, были ли они предварительно включены в пользовательские настройки варианта отчета. Мы работаем напрямую с коллекцией Настройки.Отбор.Элементы, что дает полный контроль над фильтрацией данных.

Общие рекомендации и важные моменты при работе с СКД и расшифровкой

При программной работе с СКД и расшифровкой отчетов, всегда помните о следующих важных моментах:

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

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

← На главную