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