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