При работе с Системой Компоновки Данных (СКД) в 1С:Предприятие часто возникает задача расшифровки данных отчета. Мы можем захотеть открыть тот же отчет, но с другими настройками или передать в него дополнительные отборы, соответствующие ячейке расшифровки. Однако при программной установке параметров для отчета расшифровки мы можем столкнуться с ошибкой: "невозможно применить фиксированные настройки. совпадают значения параметра". Разберем, почему возникает эта ошибка, и как эффективно передавать параметры и отборы при расшифровке.
Для начала, давайте выясним причину возникновения этой ошибки. В СКД существуют различные типы настроек, которые могут влиять на формирование отчета:
Ошибка "невозможно применить фиксированные настройки. совпадают значения параметра" возникает, когда система компоновки данных пытается объединить настройки, и обнаруживает, что один и тот же параметр или поле отбора задано одновременно как в фиксированных настройках (которые мы пытаемся передать программно, например, через параметр Отбор в ПараметрыФормы) и в пользовательских настройках, или даже в стандартных настройках выбранного варианта отчета. СКД не может однозначно определить, какое значение использовать, и сообщает о конфликте.
Рассмотрим пример кода, который приводит к этой ошибке:
ПараметрыФормы = Новый Структура;
ПараметрыФормы.Вставить("СформироватьПриОткрытии", Истина);
ПараметрыФормы.Вставить("КлючВарианта", "Расшифровка"); // Вариант отчета, возможно, имеет свои настройки
СтруктураОтбора = Новый Структура;
СтруктураОтбора.Вставить("ПериодДоставки", Период);
СтруктураОтбора.Вставить("ДатаНачала", Период.ДатаНачала);
СтруктураОтбора.Вставить("ДатаОкончания", Период.ДатаОкончания);
ПараметрыФормы.Вставить("Отбор", СтруктураОтбора); // Здесь мы пытаемся передать отбор как фиксированный параметр
ФормаРасшифровки = ПолучитьФорму(ИмяОтчета+".Форма", ПараметрыФормы, , Истина);
В этом коде мы передаем структуру Отбор как параметр формы. 1С интерпретирует это как попытку применить фиксированные настройки. Если в варианте отчета "Расшифровка" или в пользовательских настройках для этого варианта уже существуют отборы по полям "ПериодДоставки", "ДатаНачала" или "ДатаОкончания", возникнет конфликт.
Также проблема усугубляется, если в модуле объекта отчета присутствует процедура ПриКомпоновкеРезультата, где мы вручную управляем настройками компоновщика:
Процедура ПриКомпоновкеРезультата(ДокументРезультат, ДанныеРасшифровки, СтандартнаяОбработка)
СтандартнаяОбработка = Ложь;
НастройкиСКД = КомпоновщикНастроек.ПолучитьНастройки(); // Вот здесь возникнет ошибка
// ... дальнейшая программная обработка ...
КонецПроцедуры
Вызов КомпоновщикНастроек.ПолучитьНастройки() приводит к объединению всех типов настроек (стандартных, пользовательских, фиксированных), и именно в этот момент проявляется конфликт.
Чтобы избежать ошибки с фиксированными настройками, нам следует передавать динамические отборы и параметры для расшифровки не как фиксированные настройки формы, а как пользовательские настройки отчета, который мы открываем.
Мы будем открывать форму отчета, а затем, после её получения, программно изменять пользовательские настройки компоновщика в этой форме.
ПараметрыФормы. Можно передать только КлючВарианта и флаг СформироватьПриОткрытии.Вот как мы можем переделать наш исходный код:
// Шаг 1: Подготавливаем базовые параметры для открытия формы
ПараметрыФормы = Новый Структура;
ПараметрыФормы.Вставить("СформироватьПриОткрытии", Истина);
ПараметрыФормы.Вставить("КлючВарианта", "Расшифровка");
// Шаг 2: Получаем форму отчета расшифровки
// Важно: не передаем сюда параметр "Отбор", чтобы избежать конфликта с фиксированными настройками
ФормаРасшифровки = ПолучитьФорму(ИмяОтчета+".Форма", ПараметрыФормы, , Истина);
// Шаг 3: Добираемся до настроек компоновщика отчета внутри формы
// Объект формы содержит поле "Отчет", которое является объектом отчета
// Объект отчета содержит КомпоновщикНастроек
КомпоновщикНастроекРасшифровки = ФормаРасшифровки.Отчет.КомпоновщикНастроек;
// Шаг 4: Теперь мы можем работать с настройками компоновщика.
// Если нужно изменить ПараметрыДанных, то обращаемся к КомпоновщикНастроекРасшифровки.Настройки.ПараметрыДанных
// Если нужно изменить Отборы, то обращаемся к КомпоновщикНастроекРасшифровки.Настройки.Отбор
// Передаем значения Период, ДатаНачала, ДатаОкончания
// Важно: ищем элементы в основных настройках (которые объединяют пользовательские и стандартные),
// а не только в ПользовательскиеНастройки.Элементы, так как отбор может быть задан в варианте по умолчанию.
// Пример установки параметров (если они есть в схеме компоновки данных как параметры):
Для Каждого ЭлементПараметра Из КомпоновщикНастроекРасшифровки.Настройки.ПараметрыДанных Цикл
Если ЭлементПараметра.Имя = "ПериодДоставки" Тогда
ЭлементПараметра.Значение = Период;
ЭлементПараметра.Использование = Истина;
ИначеЕсли ЭлементПараметра.Имя = "ДатаНачала" Тогда
ЭлементПараметра.Значение = Период.ДатаНачала;
ЭлементПараметра.Использование = Истина;
ИначеЕсли ЭлементПараметра.Имя = "ДатаОкончания" Тогда
ЭлементПараметра.Значение = Период.ДатаОкончания;
ЭлементПараметра.Использование = Истина;
КонецЕсли;
КонецЦикла;
// Если нам нужно программно установить отборы, то это делается следующим образом (см. следующий раздел)
// Открываем форму
ФормаРасшифровки.Открыть();
Таким образом, мы избегаем прямого конфликта, поскольку не пытаемся применить "фиксированные" настройки формы. Вместо этого мы манипулируем объектом КомпоновщикНастроек уже открытой (но ещё не показанной пользователю) формы отчета.
Теперь рассмотрим более сложный случай, когда нам необходимо передать значения группировок из текущего отчета в виде отборов для отчета расшифровки. Например, мы щелкнули по строке отчета, сгруппированной по "Номенклатура" и "Склад", и хотим, чтобы отчет расшифровки показал детальные данные только по этой конкретной номенклатуре и складу. Для программного извлечения значений группировок в процедуре расшифровки подойдёт пример получения значений группировок в отчете СКД.
В этом случае нам нужно будет программно добавить или изменить элементы отбора в коллекции Настройки.Отбор.Элементы объекта КомпоновщикНастроек в форме расшифровки.
Проблема, с которой мы можем столкнуться, заключается в том, что если поле отбора не включено в пользовательские настройки по умолчанию (то есть, оно не отображается на закладке "Отборы" в настройках СКД для пользователя), то его не будет в коллекции Настройки.ПользовательскиеНастройки.Элементы. Однако, мы можем работать напрямую с коллекцией Настройки.Отбор.Элементы, которая содержит все возможные отборы, включая те, что заданы в конфигураторе или были добавлены ранее.
Разберем шаги:
Настройки компоновщика отчета расшифровки.СтруктураДанных.ЗначенияГруппировок), где ключ — это имя поля группировки, а значение — это её значение.Настройки.Отбор.Элементы.ЭлементОтбораКомпоновкиДанных и добавляем его в коллекцию.Вот пример кода, демонстрирующий этот подход:
// ... код получения ФормаРасшифровки, как показано выше ...
КомпоновщикНастроекРасшифровки = ФормаРасшифровки.Отчет.КомпоновщикНастроек;
Настройки = КомпоновщикНастроекРасшифровки.Настройки;
// СтруктураДанных.ЗначенияГруппировок - это структура,
// которую мы обычно получаем при расшифровке отчета,
// где ключ - имя поля, значение - его значение.
// Например: СтруктураДанных.ЗначенияГруппировок = Новый Структура("Номенклатура", МояНоменклатура, "Склад", МойСклад);
Для Каждого ТекЭлемент Из СтруктураДанных.ЗначенияГруппировок Цикл
// Создаем ПолеКомпоновкиДанных для поиска/создания элемента отбора
НовоеПоле = Новый ПолеКомпоновкиДанных(ТекЭлемент.Ключ);
ЭлементОтбора = Неопределено;
// Ищем существующий элемент отбора по этому полю
Для Каждого ТекЭлементОтбора Из Настройки.Отбор.Элементы Цикл
Если ТекЭлементОтбора.ЛевоеЗначение = НовоеПоле Тогда
ЭлементОтбора = ТекЭлементОтбора;
Прервать;
КонецЕсли;
КонецЦикла;
Если ЭлементОтбора = Неопределено Тогда
// Если элемент отбора не найден, создаем новый
ЭлементОтбора = Настройки.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
ЭлементОтбора.ЛевоеЗначение = Новый ПолеКомпоновкиДанных(ТекЭлемент.Ключ);
ЭлементОтбора.ВидСравнения = ВидСравненияКомпоновкиДанных.Равно;
ЭлементОтбора.ПравоеЗначение = ТекЭлемент.Значение;
ЭлементОтбора.Использование = Истина;
Иначе
// Если элемент отбора найден, обновляем его значение
ЭлементОтбора.ВидСравнения = ВидСравненияКомпоновкиДанных.Равно;
ЭлементОтбора.ПравоеЗначение = ТекЭлемент.Значение;
ЭлементОтбора.Использование = Истина;
КонецЕсли;
КонецЦикла;
// Теперь, когда все отборы установлены, можно открыть форму
ФормаРасшифровки.Открыть();
Этот подход позволяет нам гибко управлять отборами, независимо от того, были ли они предварительно включены в пользовательские настройки варианта отчета. Мы работаем напрямую с коллекцией Настройки.Отбор.Элементы, что дает полный контроль над фильтрацией данных.
При программной работе с СКД и расшифровкой отчетов, всегда помните о следующих важных моментах:
КомпоновщикНастроек через объект отчета внутри формы: ФормаОтчета.Отчет.КомпоновщикНастроек. Это обеспечивает, что вы работаете с актуальными настройками конкретного экземпляра отчета.ПриКомпоновкеРезультата: Если в модуле объекта отчета присутствует процедура ПриКомпоновкеРезультата и вы устанавливаете СтандартнаяОбработка = Ложь, это означает, что вы полностью берете на себя управление процессом компоновки. В этом случае убедитесь, что все необходимые настройки (параметры, отборы, группировки) явно применяются вами в этой процедуре к объекту КомпоновщикНастроек или к МакетКомпоновкиДанных.КлючВарианта), корректно загружается в компоновщик. Обычно это происходит автоматически при открытии формы отчета с указанным ключом варианта. После этого вы уже можете манипулировать этими загруженными настройками.Применяя эти подходы, вы сможете эффективно управлять расшифровкой отчетов СКД, программно передавать необходимые параметры и отборы, избегая распространенных ошибок, связанных с конфликтами настроек.