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