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