При обновлении типовых конфигураций, таких как 1С:Бухгалтерия предприятия 3.0, на новые релизы (например, 108-й и выше), разработчики часто сталкиваются с тем, что программный код в расширениях, отвечающий за установку отборов в динамических списках, внезапно перестает работать. Чаще всего это сопровождается ошибкой: "параметры отбора, сортировки, группировки или список отображаемых полей заданы неверно. Не найдено поле отбора Организация" (или любое другое поле).
В этой статье мы подробно разберем методы доработки динамических списков, почему это происходит, как изменилась логика работы платформы 1С:Предприятие 8.3.19 и выше, и как правильно переписать код, чтобы восстановить работоспособность системы.
Проанализируем ситуацию: поле (например, индикатор прогресса в ячейке) присутствует в запросе динамического списка и отображается на форме, однако система сообщает, что не видит его при попытке программной установки отбора. Выясним причину такого поведения. Она кроется в изменениях платформы версии 8.3.19.1522 и выше.
Ранее для ограничения прав пользователя на изменение отборов часто использовался метод УстановитьОграниченияИспользованияВОтборе(). Однако, начиная с указанных версий платформы, этот метод (а также его аналоги для группировок и порядка) был объявлен устаревшим. Главная проблема заключается в том, что теперь вызов этого метода полностью удаляет поле из коллекции доступных полей компоновщика настроек.
Когда ваш код сначала вызывает ограничение на поле, а затем пытается установить в него значение через ОбщегоНазначенияКлиентСервер.УстановитьЭлементОтбораДинамическогоСписка, система обращается к компоновщику настроек, не находит там "удаленное" поле и выбрасывает исключение.
Рассмотрим пример кода, который часто встречается в расширениях и который приводит к ошибке на новых релизах:
&НаСервере
Процедура РасшРоли_ПриСозданииНаСервереПосле(Отказ, СтандартнаяОбработка)
ЗапрещенныеВОтбореПоля = Новый Массив;
Если РольДоступна("РасшРоли_ОграничениеПоОрганизации") Тогда
ЗапрещенныеВОтбореПоля.Добавить("Организация");
// Вот эта строка делает поле "невидимым" для программного кода ниже
Список.УстановитьОграниченияИспользованияВОтборе(ЗапрещенныеВОтбореПоля);
// В этот момент поле "Организация" уже отсутствует в доступных полях,
// и следующая функция вызовет ошибку:
ОбщегоНазначенияКлиентСервер.УстановитьЭлементОтбораДинамическогоСписка(
Список, "Организация", ПолучитьОрганизациюПоУмолчанию(),
ВидСравненияКомпоновкиДанных.Равно, , Истина,
РежимОтображенияЭлементаНастройкиКомпоновкиДанных.Недоступный);
КонецЕсли;
КонецПроцедуры
Вместо устаревших методов рекомендуется использовать новые свойства динамического списка: ОграничениеИспользования и ОграничениеИспользованияРеквизитов. Они позволяют более гибко управлять доступностью полей без их полного исключения из метаданных компоновщика на лету.
Посмотрим на правильный алгоритм действий:
РежимОтображенияЭлементаНастройкиКомпоновкиДанных.Недоступный.ОграничениеИспользованияРеквизитов.Разберем по шагам, как должен выглядеть современный код в расширении для формы списка:
&НаСервере
Процедура РасшРоли_ПриСозданииНаСервереПосле(Отказ, СтандартнаяОбработка)
Если РольДоступна("РасшРоли_ОграничениеПоОрганизации") Тогда
// 1. Сначала программно устанавливаем сам отбор
// Используем стандартную функцию БСП
ОбщегоНазначенияКлиентСервер.УстановитьЭлементОтбораДинамическогоСписка(
Список,
"Организация",
ПолучитьОрганизациюПоУмолчанию(),
ВидСравненияКомпоновкиДанных.Равно,
"Организация (ограничение)", // Представление
Истина, // Использование
РежимОтображенияЭлементаНастройкиКомпоновкиДанных.Недоступный); // Пользователь не сможет его изменить
// 2. Теперь ограничиваем само поле, чтобы пользователь не мог добавить еще один отбор по нему
// Находим настройки поля в динамическом списке
ЭлементОграничения = Список.ОграничениеИспользованияРеквизитов.Найти("Организация");
Если ЭлементОграничения = Неопределено Тогда
ЭлементОграничения = Список.ОграничениеИспользованияРеквизитов.Добавить("Организация");
КонецЕсли;
// Запрещаем использование поля в пользовательских настройках отбора
ЭлементОграничения.Отбор = Ложь;
КонецЕсли;
КонецПроцедуры
Рассмотрим еще один способ, который позволяет скрыть поле из списка выбора в окне "Настроить список", но сохранить возможность программной манипуляции. Это работа напрямую с КомпоновщикомНастроек.
Проанализируем пример реализации:
// Получаем идентификатор поля
ПолеОрганизация = Новый ПолеКомпоновкиДанных("Организация");
// Ищем поле в доступных полях отбора
Для Каждого ДоступноеПоле Из Список.КомпоновщикНастроек.Настройки.ДоступныеПоляОтбора.Элементы Цикл
Если ДоступноеПоле.Поле = ПолеОрганизация Тогда
// Снимаем флаг использования — поле исчезнет из выбора пользователем,
// но останется валидным для кода
ДоступноеПоле.Использование = Ложь;
КонецЕсли;
КонецЦикла;
Посмотрим на дополнительные факторы, которые могут влиять на появление ошибки "Не найдено поле отбора" в контексте расширений:
Список также корректно перенесся. Иногда после обновления основной конфигурации запрос динамического списка в расширении "залипает" в старом состоянии. Попробуйте обновить текст запроса динамического списка в расширении.ОсновнаяТаблица в настройках динамического списка в расширении. Если она не указана, платформа может не понимать, к каким полям разрешен отбор.ВЫБРАТЬ Документ.Организация КАК ОрганизацияКомпании, то и в программном коде нужно обращаться к "ОрганизацияКомпании".Подведем итог: Если вы столкнулись с подобной ошибкой после обновления на платформу 8.3.19+, первым делом откажитесь от метода УстановитьОграниченияИспользованияВОтборе(). Используйте комбинацию установки отбора в режиме Недоступный и управление коллекцией ОграничениеИспользованияРеквизитов. Это обеспечит стабильную работу кода и корректное поведение интерфейса для пользователя.