Как программно передать пользовательские настройки из одного отчета в другой в 1С

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

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

Почему прямая передача настроек не работает?

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

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

Способ 1. Программное сопоставление по именам полей и параметров

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

Рассмотрим алгоритм реализации. Сначала нам нужно подготовить процедуру, которая будет перебирать пользовательские настройки. Основная сложность здесь в том, что ПользовательскиеНастройки — это плоская структура, и чтобы понять, к какому полю относится конкретный элемент отбора, нам нужно обратиться к основной коллекции Настройки через идентификатор.

Разберем пример кода для переноса параметров:


// В форме источника (например, обработки)
ПараметрыФормы = Новый Структура;
КоллекцияНастроек = Новый Соответствие;

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

ПараметрыФормы.Вставить("ПереданныеПараметрыСКД", КоллекцияНастроек);
ОткрытьФорму("Отчет.НужныйОтчет.Форма", ПараметрыФормы);

Затем в форме отчета-приемника, в обработчике ПриСозданииНаСервере, нам нужно выполнить обратную операцию: найти параметры по именам и установить им переданные значения.


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

Способ 2. Использование фиксированных идентификаторов в Конфигураторе

Проанализируем более элегантный способ, который позволяет избежать сложного парсинга коллекций. Если вы имеете доступ к разработке обоих объектов (и источника, и приемника), вы можете задать **имена пользовательских настроек** вручную.

  1. Откройте схему компоновки данных (СКД).
  2. Перейдите на закладку "Настройки".
  3. Выберите нужный параметр или отбор.
  4. В нижней части окна свойств найдите кнопку "Свойства элемента пользовательских настроек" (иконка с ключом).
  5. В поле "Имя" укажите строковый идентификатор, например, "ФильтрПоОрганизации".

Важный момент: Если в обоих отчетах для логически одинаковых настроек указаны идентичные имена в этом поле, платформа 1С сможет сопоставить их гораздо проще. При передаче структуры через ЗагрузитьПользовательскиеНастройки() система будет ориентироваться на эти имена, а не на GUID-ы.

Способ 3. Передача через стандартный параметр формы "Отбор"

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

Выясним, как это работает. При открытии формы система автоматически анализирует переданную структуру и пытается найти поля с такими же именами в настройках компоновщика. Если соответствие найдено, отбор устанавливается автоматически.


СтруктураОтбора = Новый Структура;
СтруктураОтбора.Вставить("Организация", ВыбраннаяОрганизация);
СтруктураОтбора.Вставить("Склад", ВыбранныйСклад);

ПараметрыФормы = Новый Структура("Отбор", СтруктураОтбора);
ОткрытьФорму("Отчет.Продажи.Форма", ПараметрыФормы);

Этот метод наиболее предпочтителен, так как он не требует написания кода в форме-приемнике (если это типовой отчет) и работает максимально быстро. Однако он не подходит для сложных условий (например, отборов типа "ИЛИ" или вложенных групп).

Способ 4. Программное создание объекта и загрузка настроек

Рассмотрим ситуацию, когда нам нужно подготовить отчет к запуску полностью программно, включая заполнение всех настроек компоновщика, и только потом показать форму пользователю. В этом случае мы можем создать объект отчета в памяти.


// Создаем объект отчета программно
ОтчетОбъект = Отчеты.МойОтчет.Создать();
Компоновщик = ОтчетОбъект.КомпоновщикНастроек;

// Загружаем настройки (здесь можно применить алгоритм сопоставления из Способа 1)
// ... установка значений в Компоновщик.ПользовательскиеНастройки ...

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

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

Резюме и рекомендации

Проанализировав все способы, можно сделать следующие выводы:

Помните, что ПользовательскиеНастройки — это лишь "верхушка айсберга". Всегда проверяйте свойство Использование для каждого элемента, иначе даже при наличии значения фильтр может не примениться в итоговом результате отчета.

← На главную