Как устранить ошибку «Невозможно применить фиксированные настройки» при установке отбора в 1С?

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

При попытке программно ограничить выбор значений в элементе формы или табличной части разработчики нередко сталкиваются с ситуацией, когда платформа 1С выбрасывает исключение: «Невозможно применить фиксированные настройки. Пересекаются элементы отбора». Разберем механику этой проблемы, выясним, почему она происходит, и подробно рассмотрим проверенные способы её решения.

Почему возникает конфликт настроек компоновщика

Проанализируем архитектуру работы динамического списка формы выбора. Когда мы передаем условия фильтрации через свойство элемента ПараметрыВыбора или через структуру Параметры.Отбор при открытии формы, платформа автоматически помещает указанные условия в коллекцию ФиксированныеНастройки динамического списка.

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

Способ 1. Установка отбора по списку ссылок через ПараметрыВыбора

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

Разберем пример программного заполнения параметров выбора для элемента управления:


МассивПараметров = Новый Массив;
// МассивСсылок содержит отобранные ссылки нужного справочника
МассивПараметров.Добавить(Новый ПараметрВыбора("Отбор.Ссылка", МассивСсылок));

НовыеПараметрыВыбора = Новый ФиксированныйМассив(МассивПараметров);
Элементы.СвойстваСвойство.ПараметрыВыбора = НовыеПараметрыВыбора;

Обратите внимание на важную особенность табличных частей: свойство ПараметрыВыбора относится к элементу формы (колонке), а не к конкретной строке. Если вы меняете параметры выбора у колонки, отбор повлияет на выбор данных во всех строках таблицы одновременно. Если отбор должен зависеть от данных текущей строки, предпочтительнее использовать второй или третий способ.

Способ 2. Открытие формы через событие «НачалоВыбора» с уникальным ключом

Рассмотрим универсальный вариант, который позволяет изолировать контекстный выбор от общих пользовательских настроек формы. Для этого перехватим событие элемента управления НачалоВыбора и откроем форму программно с указанием параметров.

  1. В свойствах поля формы создадим обработчик события НачалоВыбора.
  2. Установим признак СтандартнаяОбработка = Ложь, чтобы отменить стандартное открытие формы выбора платформой.
  3. Сформируем структуру параметров и передадим уникальный КлючНазначенияИспользования. Это заставит платформу сохранять и читать пользовательские настройки отдельно от стандартной формы справочника.

Разберем пример кода обработчика:


&НаКлиенте
Процедура ТабличнаяЧастьСвойствоНачалоВыбора(Элемент, ДанныеВыбора, СтандартнаяОбработка)
    
    СтандартнаяОбработка = Ложь;
    
    ТекущаяСтрока = Элементы.ТабличнаяЧасть.ТекущиеДанные;
    Если ТекущаяСтрока = Неопределено Тогда
        Возврат;
    КонецЕсли;
    
    ПараметрыОтбора = Новый Структура;
    ПараметрыОтбора.Вставить("Владелец", ТекущаяСтрока.ВладелецСвойства);
    
    ПараметрыФормы = Новый Структура;
    ПараметрыФормы.Вставить("Отбор", ПараметрыОтбора);
    ПараметрыФормы.Вставить("КлючНазначенияИспользования", "КонтекстныйВыборСвойств");
    
    ОткрытьФорму("Справочник.ЗначенияСвойствОбъектов.ФормаВыбора", ПараметрыФормы, Элемент);
    
КонецПроцедуры

Способ 3. Очистка конфликтного отбора в СписокПередЗагрузкойПользовательскихНастроекНаСервере

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

В модуле формы выбора определим обработчик таблицы СписокПередЗагрузкойПользовательскихНастроекНаСервере. В переданной коллекции Настройки найдем элементы отбора, совпадающие с фиксированными параметрами, и удалим их:


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

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

Способ 4. Переопределение выбора через ОбработкаПолученияДанныхВыбора

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

В модуле менеджера выбираемого объекта реализуем обработчик события ОбработкаПолученияДанныхВыбора. В нем выполним запрос и напрямую поместим результат в коллекцию ДанныеВыбора:


Процедура ОбработкаПолученияДанныхВыбора(ДанныеВыбора, Параметры, СтандартнаяОбработка)
    
    СтандартнаяОбработка = Ложь;
    
    ДанныеВыбора = Новый СписокЗначений;
    
    Запрос = Новый Запрос;
    Запрос.Текст = 
        "ВЫБРАТЬ
        |	Спр.Ссылка КАК Ссылка,
        |	Спр.Наименование КАК Наименование
        |ИЗ
        |	Справочник.ЗначенияСвойствОбъектов КАК Спр
        |ГДЕ
        |	НЕ Спр.ПометкаУдаления
        |	И Спр.Наименование ПОДОБНО &СтрокаПоиска + ""%""";
        
    Запрос.УстановитьПараметр("СтрокаПоиска", Параметры.СтрокаАвтоПодбора);
    
    Выборка = Запрос.Выполнить().Выбрать();
    Пока Выборка.Следующий() Цикл
        ДанныеВыбора.Добавить(Выборка.Ссылка, Выборка.Наименование);
    КонецЦикла;
    
КонецПроцедуры

Этот метод полностью устраняет конфликт компоновщика настроек, так как динамический список и системное хранилище пользовательских настроек в этом сценарии вовсе не задействуются.

Способ 5. Сброс зависших настроек пользователя

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


// Очистка сохраненных настроек формы для текущего пользователя
ХранилищеСистемныхНастроек.Удалить(
    "Справочник.ЗначенияСвойствОбъектов.Форма.ФормаВыбора", 
    "", 
    ИмяПользователя()
);

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

← На главную