Почему перестал работать программный отбор в динамическом списке и как это исправить?

Программист 1С v8.3 (Управляемые формы) 1C:Бухгалтерия
← На главную

При обновлении типовых конфигураций, таких как 1С:Бухгалтерия предприятия 3.0, на новые релизы (например, 108-й и выше), разработчики часто сталкиваются с тем, что программный код в расширениях, отвечающий за установку отборов в динамических списках, внезапно перестает работать. Чаще всего это сопровождается ошибкой: "параметры отбора, сортировки, группировки или список отображаемых полей заданы неверно. Не найдено поле отбора Организация" (или любое другое поле).

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

Разберем причину возникновения ошибки

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

Ранее для ограничения прав пользователя на изменение отборов часто использовался метод УстановитьОграниченияИспользованияВОтборе(). Однако, начиная с указанных версий платформы, этот метод (а также его аналоги для группировок и порядка) был объявлен устаревшим. Главная проблема заключается в том, что теперь вызов этого метода полностью удаляет поле из коллекции доступных полей компоновщика настроек.

Когда ваш код сначала вызывает ограничение на поле, а затем пытается установить в него значение через ОбщегоНазначенияКлиентСервер.УстановитьЭлементОтбораДинамическогоСписка, система обращается к компоновщику настроек, не находит там "удаленное" поле и выбрасывает исключение.

Проанализируем старый (нерабочий) подход

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


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

Рассмотрим решение через новые свойства платформы

Вместо устаревших методов рекомендуется использовать новые свойства динамического списка: ОграничениеИспользования и ОграничениеИспользованияРеквизитов. Они позволяют более гибко управлять доступностью полей без их полного исключения из метаданных компоновщика на лету.

Посмотрим на правильный алгоритм действий:

  1. Сначала устанавливаем значение отбора. Программная установка элемента отбора должна происходить до того, как на поле будут наложены жесткие ограничения.
  2. Устанавливаем режим отображения. Если нужно, чтобы пользователь не видел этот отбор и не мог его удалить, используйте РежимОтображенияЭлементаНастройкиКомпоновкиДанных.Недоступный.
  3. Используем свойства полей. Для запрета интерактивного добавления поля в новые отборы используем коллекцию ОграничениеИспользованияРеквизитов.

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

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


&НаСервере
Процедура РасшРоли_ПриСозданииНаСервереПосле(Отказ, СтандартнаяОбработка)

    Если РольДоступна("РасшРоли_ОграничениеПоОрганизации") Тогда
        
        // 1. Сначала программно устанавливаем сам отбор
        // Используем стандартную функцию БСП
        ОбщегоНазначенияКлиентСервер.УстановитьЭлементОтбораДинамическогоСписка(
            Список, 
            "Организация", 
            ПолучитьОрганизациюПоУмолчанию(), 
            ВидСравненияКомпоновкиДанных.Равно, 
            "Организация (ограничение)", // Представление
            Истина, // Использование
            РежимОтображенияЭлементаНастройкиКомпоновкиДанных.Недоступный); // Пользователь не сможет его изменить
            
        // 2. Теперь ограничиваем само поле, чтобы пользователь не мог добавить еще один отбор по нему
        // Находим настройки поля в динамическом списке
        ЭлементОграничения = Список.ОграничениеИспользованияРеквизитов.Найти("Организация");
        Если ЭлементОграничения = Неопределено Тогда
            ЭлементОграничения = Список.ОграничениеИспользованияРеквизитов.Добавить("Организация");
        КонецЕсли;
        
        // Запрещаем использование поля в пользовательских настройках отбора
        ЭлементОграничения.Отбор = Ложь;
        
    КонецЕсли;

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

Альтернативный метод через ДоступныеПоляОтбора

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

Проанализируем пример реализации:


// Получаем идентификатор поля
ПолеОрганизация = Новый ПолеКомпоновкиДанных("Организация");

// Ищем поле в доступных полях отбора
Для Каждого ДоступноеПоле Из Список.КомпоновщикНастроек.Настройки.ДоступныеПоляОтбора.Элементы Цикл
    Если ДоступноеПоле.Поле = ПолеОрганизация Тогда
        // Снимаем флаг использования — поле исчезнет из выбора пользователем, 
        // но останется валидным для кода
        ДоступноеПоле.Использование = Ложь; 
    КонецЕсли;
КонецЦикла;

Важные нюансы при работе в расширениях

Посмотрим на дополнительные факторы, которые могут влиять на появление ошибки "Не найдено поле отбора" в контексте расширений:

Подведем итог: Если вы столкнулись с подобной ошибкой после обновления на платформу 8.3.19+, первым делом откажитесь от метода УстановитьОграниченияИспользованияВОтборе(). Используйте комбинацию установки отбора в режиме Недоступный и управление коллекцией ОграничениеИспользованияРеквизитов. Это обеспечит стабильную работу кода и корректное поведение интерфейса для пользователя.

← На главную