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