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