Как в СКД ограничить выбор строкового поля или параметра своим списком значений?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

При разработке отчетов на базе Системы компоновки данных (СКД) часто возникает задача ограничить выбор значений для определенного поля или параметра. Если поле имеет ссылочный тип (например, СправочникСсылка.Номенклатура), платформа «1С:Предприятие» автоматически предоставляет пользователю удобную форму выбора. Однако, если поле или параметр имеют тип Строка, стандартное поведение системы предлагает лишь ручной ввод текстовых значений.

Что делать, если набор возможных текстовых значений ограничен и заранее известен (например, хранится во временной таблице, таблице значений или формируется динамически при открытии отчета)? В этой статье мы подробно разберем, как правильно реализовать выбор из предопределенного списка для строковых полей в СКД, рассмотрим основные проблемы, с которыми сталкиваются разработчики, и найдем пути их решения.


Метод 1. Программное ограничение на уровне схемы компоновки данных

Самый правильный и архитектурно верный способ — установить доступные значения непосредственно в схеме компоновки данных. Для этого у параметров схемы и полей наборов данных существует специализированный метод УстановитьДоступныеЗначения(). Этот метод принимает на вход объект типа СписокЗначений.

Рассмотрим, как правильно реализовать этот подход в модуле объекта отчета. Лучше всего использовать этот код при инициализации отчета или непосредственно перед компоновкой результата.

Разберем по шагам пример кода, который необходимо разместить в модуле объекта отчета:


Процедура ИнициализироватьОграниченияСписка() Экспорт

    // 1. Формируем список возможных строковых значений
    СписокВариантов = Новый СписокЗначений;
    СписокВариантов.Добавить("Премиум", "Премиум-сегмент");
    СписокВариантов.Добавить("Стандарт", "Стандартный класс");
    СписокВариантов.Добавить("Эконом", "Эконом-класс");
    
    // 2. Устанавливаем доступные значения для параметра схемы
    ПараметрСхемы = СхемаКомпоновкиДанных.Параметры.Найти("КлассОбслуживания");
    Если ПараметрСхемы <> Неопределено Тогда
        ПараметрСхемы.УстановитьДоступныеЗначения(СписокВариантов);
    КонецЕсли;
    
    // 3. Устанавливаем доступные значения для поля набора данных (для использования в отборах)
    ПолеСхемы = СхемаКомпоновкиДанных.НаборыДанных[0].Поля.Найти("КлассОбслуживания");
    Если ПолеСхемы <> Неопределено Тогда
        ПолеСхемы.УстановитьДоступныеЗначения(СписокВариантов);
    КонецЕсли;
    
    // 4. Переинициализируем компоновщик настроек, чтобы изменения применились к структуре
    ИсточникНастроек = Новый ИсточникДоступныхНастроекКомпоновкиДанных(СхемаКомпоновкиДанных);
    КомпоновщикНастроек.Инициализировать(ИсточникНастроек);

КонецПроцедуры

Важный нюанс: Обратите внимание на шаг №4. Если просто изменить схему компоновки данных и не выполнить повторную инициализацию КомпоновщикаНастроек, пользователь не увидит изменений в интерфейсе. Компоновщик настроек должен «узнать», что состав доступных полей и параметров в схеме изменился.


Проблема кэширования настроек («Быстрый доступ» не обновляется)

При использовании первого метода разработчики часто сталкиваются с неприятным поведением платформы: при нажатии на кнопку «Настройки...» в форме отчета список выбора для параметра отображается корректно, но на самой форме отчета (в области быстрых настроек/быстрого доступа) параметр по-прежнему выглядит как обычная строка ввода без кнопки выбора.

Выясним причину этого поведения. Дело в том, что 1С активно использует кэширование структуры настроек пользователя. При открытии отчета система пытается восстановить последние сохраненные настройки конкретного пользователя из системного хранилища. Если структура этих настроек была сохранена до того, как вы программно ограничили список значений, платформа визуализирует поле ввода по старым правилам.

Для решения этой проблемы на этапе разработки и тестирования необходимо выполнить сброс пользовательских настроек к стандартным. В пользовательском режиме это делается через меню «Еще» -> «Установить стандартные настройки».

Если вам требуется гарантировать сброс кэша программно при изменении логики отчета у конечных пользователей, можно применить принудительную загрузку настроек по умолчанию в модуле формы отчета:


&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
    
    // Если отчет открывается впервые или изменилась структура, принудительно устанавливаем настройки по умолчанию
    Если Не ЗначениеЗаполнено(Параметры.КлючВарианта) Тогда
        Отчет.КомпоновщикНастроек.ЗагрузитьНастройки(Отчет.СхемаКомпоновкиДанных.НастройкиПоУмолчанию);
    КонецЕсли;
    
КонецПроцедуры

Метод 2. Обходной путь через элементы управляемой формы (Быстрое решение)

Если сброс пользовательских настроек по каким-то причинам нежелателен или вам требуется абсолютно гарантированное отображение списка выбора в области быстрых настроек прямо «здесь и сейчас», можно прибегнуть к изменению свойств элементов формы.

Этот метод основан на непосредственном обращении к автогенерируемым элементам формы компоновщика настроек. Мы переводим поле ввода в режим выбора из списка и принудительно загружаем туда наш массив значений.

Проанализируем пример реализации данного метода в модуле формы отчета:


&НаКлиенте
Процедура ПриОткрытии(Отказ)
    ЗаполнитьБыстрыйВыборСтроковогоПараметра();
КонецПроцедуры

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

Важное предупреждение: Обращение к элементам формы по жестко заданному строковому имени (например, "КомпоновщикНастроекПользовательскиеНастройкиЭлемент0Значение") является «костылем» (workaround). Индексы элементов в коллекции пользовательских настроек могут измениться при любом незначительном редактировании схемы компоновки данных в конфигураторе (например, если вы добавите новый параметр выше текущего или измените порядок вывода полей). Используйте этот метод с осторожностью и только тогда, когда структура пользовательских настроек стабильна.


Метод 3. Динамический поиск элемента формы по идентификатору настройки (Надежный вариант Ме can-2)

Чтобы избежать проблем с изменением индексов элементов формы при редактировании схемы, мы можем программно определить, какой именно элемент формы связан с нужным нам параметром СКД. Для этого используется связь по идентификатору пользовательской настройки. При необходимости детальной проработки взаимодействия элементов интерфейса с отчетом можно использовать методику стыковки элементов управляемой формы и пользовательских настроек СКД.

Рассмотрим более надежный алгоритм динамического связывания списка выбора:


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

КонецПроцедуры

Метод 4. Использование механизмов БСП (Библиотека Стандартных Подсистем)

Если ваша конфигурация построена на базе БСП (что справедливо для большинства современных типовых конфигураций, таких как 1С:ERP, 1С:Комплексная автоматизация, 1С:Управление торговлей, 1С:Бухгалтерия), ручное манипулирование элементами формы считается плохой практикой.

В БСП предусмотрены штатные инструменты для управления интерфейсом отчетов. В частности, интеграция логики динамического изменения параметров отчета выполняется через переопределяемый модуль отчета или с помощью обработчиков в модуле формы.

Для корректной работы в экосистеме БСП рекомендуется задействовать специализированное событие формы отчета ПослеЗаполненияПанелиБыстрыхНастроек (или аналогичные процедуры общего модуля ОтчетыКлиентПереопределяемый), где можно централизованно и безопасно управлять свойствами элементов управления параметров.


Резюме и рекомендации

Проанализировав все варианты решения задачи, можно составить следующий свод правил для разработчика:

  1. Всегда начинайте с изменения Схемы (Метод 1). Установка доступных значений через УстановитьДоступныеЗначения() для параметров и полей набора данных — это самый чистый и правильный способ с точки зрения архитектуры СКД.
  2. Не забывайте про инициализацию. После изменения схемы программным путем обязательно вызывайте переинициализацию компоновщика настроек с новым ИсточникомДоступныхНастроекКомпоновкиДанных.
  3. Помните про кэш пользователей. Если при тестировании вы не видите изменений в режиме «быстрого доступа» на форме — выполните сброс настроек отчета к стандартным.
  4. Используйте настройку элементов формы (Метод 2 и 3) как осознанный обходной путь. Если вам необходимо обойти жесткое кэширование без сброса пользовательских настроек или список выбора должен кардинально меняться «на лету» в зависимости от других интерактивных действий пользователя на форме.
← На главную