Как бороться с ошибкой "Невозможно применить фиксированные настройки. Пересекаются элементы отбора." в формах списков 1С?

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

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

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

Понимание природы фиксированных настроек и причины конфликта

Прежде чем перейти к решениям, давайте разберемся, что такое "фиксированные настройки" и откуда берется отбор, вызывающий конфликт. Фиксированные настройки в 1С:Предприятии — это предопределенные настройки, которые имеют приоритет над другими, включая пользовательские. Они используются как в отчетах, так и в формах списков и выбора для того, чтобы ограничить изменения, вносимые пользователем или программой.

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

  1. Передача отбора через параметры формы: Когда одна форма открывает другую форму списка или выбора (например, при выборе значения в поле ввода), она может передавать отбор в виде параметра. Этот отбор попадает в свойство открываемой формы Форма.Параметры.Отбор. Система рассматривает такие отборы как своего рода "фиксированные" для данного сеанса открытия формы.
  2. "Связи параметров выбора": Часто источником такого фиксированного отбора являются "Связи параметров выбора", настроенные для реквизитов метаданных или непосредственно в форме. Например, для поля "Договор" может быть настроена связь, которая автоматически фильтрует договоры по выбранному "Контрагенту". Если в форме платежного поручения поле "Исполнительный лист" ссылается на документ, для которого настроена связь с отбором по "Организации", этот отбор автоматически будет передан в параметры открываемой формы списка документов.
  3. Автоматический пользовательский отбор: Если вы программно или пользовательски уже установили отбор по тому же полю (например, "Организация"), и этот отбор был сохранен в пользовательских настройках или применен в расширении, то при наличии фиксированного отбора по тому же полю возникнет конфликт. Платформа не может однозначно решить, какой из отборов применить, и выдает ошибку. Она не объединяет их по "И", а считает пересекающимися.

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

Способы борьбы с конфликтом фиксированных и пользовательских отборов

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

1. Программный обход через модификацию параметров формы при создании на сервере (решение автора)

Одним из наиболее эффективных способов борьбы с этой проблемой, особенно когда фиксированный отбор приходит через параметры формы, является перехват момента создания формы на сервере и программное изменение её параметров.

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

  1. Извлечь значение этого фиксированного отбора.
  2. Удалить его из Форма.Параметры.Отбор, чтобы он больше не считался фиксированным.
  3. Перенести этот отбор в обычные пользовательские настройки динамического списка, чтобы он применялся как обычный, программно установленный отбор.

Рассмотрим по шагам, как это можно реализовать в расширении:

Шаг 1: Перехват события ПриСозданииНаСервере

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

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


// В расширении, в модуле формы, для которой нужен обход
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
    // Выполняем действия типовой конфигурации, если это переопределенная процедура
    // или вызываем процедуру из основной конфигурации
    // ВызовПроцедурыИсходнойКонфигурации(ЭтотОбъект, "ПриСозданииНаСервере", Отказ, СтандартнаяОбработка);

    // Анализируем параметры формы
    АнализироватьПараметрыОтбораОрганизации(ЭтотОбъект);

    // ... дальнейший код, если есть ...
КонецПроцедуры

&НаСервере
Процедура АнализироватьПараметрыОтбораОрганизации(Форма)

    // Проверяем наличие отбора по "Организации" в параметрах формы
    ЗначениеОтбораПоОрганизации = Неопределено;
    Если Форма.Параметры.Отбор.Свойство("Организация", ЗначениеОтбораПоОрганизации) Тогда

        // Отбор по Организации найден в фиксированных настройках формы.
        // Удаляем его из фиксированных параметров, чтобы избежать конфликта.
        Форма.Параметры.Отбор.Удалить("Организация");

        // Теперь нам нужно применить этот отбор как пользовательский.
        // Для этого мы можем использовать функцию БСП
        // ОбщегоНазначенияКлиентСервер.УстановитьЭлементОтбораДинамическогоСписка
        // или напрямую добавить в пользовательские настройки динамического списка формы.

        // Предположим, что динамический список на форме называется "Список"
        // Если это форма выбора, то часто это свойство Формы.ДинамическийСписок
        ДинамическийСписок = Форма.Список; 

        Если ДинамическийСписок <> Неопределено Тогда

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

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

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

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

        КонецЕсли;
    КонецЕсли;

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

Важные моменты:

  1. Убедитесь, что вы работаете с правильным объектом динамического списка на форме (часто это Форма.Список или Элементы.Список).
  2. Использование ОбщегоНазначенияКлиентСервер.УстановитьЭлементОтбораДинамическогоСписка (сообщение 8) является предпочтительным, так как это стандартный и поддерживаемый БСП метод работы с отборами динамических списков. Он заботится о корректном формировании элемента отбора и его применении.
  3. После программного изменения настроек отбора, в некоторых случаях может потребоваться явное обновление динамического списка, чтобы изменения вступили в силу.

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

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

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

Рассмотрим пример кода для данного обработчика:


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

    // 1. Проверяем, есть ли фиксированный отбор по Организации в параметрах формы.
    // Это означает, что форма открыта с предопределенным отбором.
    ФиксированныйОтборОрганизация = Неопределено;
    Если ЭтаФорма.Параметры.Отбор.Свойство("Организация", ФиксированныйОтборОрганизация) Тогда

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

        ИндексУдаления = -1;
        Для Индекс = 0 По Настройки.Элементы.Количество() - 1 Цикл
            ЭлементНастройки = Настройки.Элементы[Индекс];

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

        // Если решили удалять элемент, то удаляем его после завершения цикла
        // (чтобы избежать проблем с изменением коллекции в цикле)
        // Если ИндексУдаления <> -1 Тогда
        //     Настройки.Элементы.Удалить(Настройки.Элементы[ИндексУдаления]);
        // КонецЕсли;

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

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

    КонецЕсли;

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

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

3. Использование функций БСП для управления отбором

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

Применение: Эта функция позволяет программно добавить или изменить элемент отбора для динамического списка, при этом корректно работая с его настройками. Её удобно использовать после того, как вы удалили конфликтный отбор из Форма.Параметры.Отбор (как в первом способе), чтобы затем применить его как обычный пользовательский отбор.


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

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

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

4. Изменение запроса динамического списка

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

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


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

        // Добавляем условие в запрос
        Если Не Форма.Список.ПроизвольныйЗапрос Тогда
            Форма.Список.ПроизвольныйЗапрос = Истина;
            Форма.Список.ТекстЗапроса = "ВЫБРАТЬ
                                       |    ПлатежноеПоручение.Ссылка,
                                       |    ...
                                       |ИЗ
                                       |    Документ.ПлатежноеПоручение КАК ПлатежноеПоручение
                                       |ГДЕ
                                       |    ПлатежноеПоручение.Организация = &ПараметрОрганизация";
        КонецЕсли;

        Форма.Список.Параметры.УстановитьЗначениеПараметра("ПараметрОрганизация", ЗначениеОтбораПоОрганизации);
        Форма.Список.Обновить();
    КонецЕсли;
КонецПроцедуры

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

5. Анализ и изменение "Связей параметров выбора"

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

  1. В свойствах метаданных: Проверьте свойства реквизитов (например, реквизита "Исполнительный лист" в платежном поручении) в конфигураторе. Возможно, для них на уровне объекта метаданных настроены связи параметров выбора, которые автоматически передают отбор по организации. Если этот отбор не является критически важным или может быть реализован другими способами, рассмотрите возможность его изменения или удаления.
  2. Настройка в конкретных формах: Связи параметров выбора также могут быть уточнены или переопределены непосредственно в свойствах элементов формы. Если вы находите такой элемент, который порождает фиксированный отбор, вы можете программно отключить его или изменить условия в обработчиках типа ПриИзменении для поля-источника связи.

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

Важные рекомендации и заключение

При работе с конфликтами отборов в 1С:Предприятии всегда учитывайте следующие моменты:

  1. Расширения: Всегда старайтесь реализовывать решения через расширения, чтобы сохранить возможность бесшовных обновлений типовых конфигураций.
  2. Тестирование: Любые изменения, касающиеся отборов и настроек форм, должны быть тщательно протестированы во всех возможных сценариях использования, включая выбор из разных документов, работу с разными пользователями и разными правами доступа.
  3. Производительность: Некоторые программные обходы могут незначительно влиять на производительность при открытии форм. Оценивайте это влияние на реальных данных.
  4. Оценка целесообразности: Прежде чем внедрять сложное программное решение, убедитесь, что фиксированный отбор действительно необходим в том виде, в котором он вызывает конфликт. Возможно, логику отбора можно изменить на более гибкую.

В целом, проблема конфликта фиксированных и пользовательских отборов является известной особенностью платформы 1С. Хотя платформа не предусматривает прямого объединения отборов по "И" для одного и того же поля, существуют эффективные программные методы обхода. Мы рассмотрели несколько таких подходов, включая перехват параметров формы, использование событий динамического списка и функций БСП. Выбор конкретного метода зависит от специфики вашей задачи, версии платформы и конфигурации.

← На главную