В процессе разработки на платформе 1С 8.3 часто возникает необходимость не просто открыть форму выбора справочника, а предварительно ограничить список доступных элементов сложным условием. Стандартная передача структуры в параметре Отбор отлично работает для простых сравнений на равенство, но когда требуется реализовать логику вида «Поле1 равно Значению И (Поле2 больше Даты ИЛИ Поле2 не заполнено)», разработчику приходится обращаться к компоновщику настроек динамического списка.
В этой статье мы подробно разберем, как программно реализовать сложные группировки условий, как правильно обрабатывать пользовательские настройки, чтобы они не перекрывали программный фильтр, и какие нюансы следует учитывать при работе с управляемыми формами.
Рассмотрим ситуацию, когда нам нужно открыть форму выбора сотрудников, отобрав их по конкретному физическому лицу и состоянию увольнения. Условие должно звучать так: «Физическое лицо совпадает с выбранным, а дата увольнения либо больше указанной даты, либо не заполнена вовсе».
Для реализации такой логики мы используем событие НачалоВыбора для элемента формы. Разберем по шагам код, который позволяет программно сконструировать дерево отборов:
&НаКлиенте
Процедура ТабДанныхСотрудникНачалоВыбора(Элемент, ДанныеВыбора, СтандартнаяОбработка)
// Отключаем стандартное открытие, так как будем открывать форму программно
СтандартнаяОбработка = Ложь;
// Получаем форму выбора
Форма = ОткрытьФорму("Справочник.Сотрудники.ФормаВыбора", , Элемент);
Список = Форма.Список;
Отбор = Список.КомпоновщикНастроек.Настройки.Отбор;
// 1. Добавляем простое условие по ФизЛицу (оно будет действовать как "И" к остальным)
ЭлементОтбораФизЛицо = Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
ЭлементОтбораФизЛицо.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("ФизическоеЛицо");
ЭлементОтбораФизЛицо.ВидСравнения = ВидСравненияКомпоновкиДанных.Равно;
ЭлементОтбораФизЛицо.ПравоеЗначение = Элементы.ТабДанных.ТекущиеДанные.ФизическоеЛицо;
ЭлементОтбораФизЛицо.Использование = Истина;
// 2. Создаем группу условий для реализации логики "ИЛИ"
ГруппаИЛИ = Отбор.Элементы.Добавить(Тип("ГруппаЭлементовОтбораКомпоновкиДанных"));
ГруппаИЛИ.ТипГруппы = ТипГруппыЭлементовОтбораКомпоновкиДанных.ГруппаИли;
ГруппаИЛИ.Использование = Истина;
// 3. Добавляем первое условие в группу ИЛИ: ДатаУвольнения >= НужнойДаты
ЭлементДатаБольше = ГруппаИЛИ.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
ЭлементДатаБольше.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("ДатаУвольнения");
ЭлементДатаБольше.ВидСравнения = ВидСравненияКомпоновкиДанных.БольшеИлиРавно;
ЭлементДатаБольше.ПравоеЗначение = Элементы.ТабДанных.ТекущиеДанные.ДатаОкончания;
ЭлементДатаБольше.Использование = Истина;
// 4. Добавляем второе условие в группу ИЛИ: ДатаУвольнения не заполнена
ЭлементДатаПустая = ГруппаИЛИ.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
ЭлементДатаПустая.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("ДатаУвольнения");
ЭлементДатаПустая.ВидСравнения = ВидСравненияКомпоновкиДанных.НеЗаполнено;
ЭлементДатаПустая.Использование = Истина;
КонецПроцедуры
В данном примере мы используем объект ПолеКомпоновкиДанных, чтобы указать системе, по какому полю динамического списка будет идти фильтрация. Важно помнить, что имена полей должны соответствовать именам в схеме компоновки данных (СКД), на которой построен список.
Одной из проблем программного наложения отборов является то, что платформа 1С сохраняет настройки пользователя (фильтры, которые пользователь ставил вручную). Если в сохраненных настройках уже есть фильтр по тому же полю, ваш программный код может либо продублировать его, либо вступить в конфликт, из-за чего список окажется пустым.
Проанализируем ситуацию: чтобы программный отбор гарантированно применился, мы можем либо очистить пользовательские настройки, либо принудительно внедрить наш отбор прямо в них. Рассмотрим вариант с очисткой и установкой режима отображения:
// ... (после открытия формы)
// Очищаем существующие пользовательские настройки отборов
Для Каждого ЭлементНастройки Из Список.КомпоновщикНастроек.ПользовательскиеНастройки.Элементы Цикл
Если ТипЗнч(ЭлементНастройки) = Тип("ОтборКомпоновкиДанных") Тогда
ЭлементНастройки.Элементы.Очистить();
// Повторяем логику добавления элементов, но уже внутрь ЭлементНастройки.Элементы
// Это гарантирует, что пользователь увидит эти отборы и они будут активны
Группа = ЭлементНастройки.Элементы.Добавить(Тип("ГруппаЭлементовОтбораКомпоновкиДанных"));
Группа.ТипГруппы = ТипГруппыЭлементовОтбораКомпоновкиДанных.ГруппаИли;
// ... заполнение группы ...
КонецЕсли;
КонецЦикла;
Важный нюанс: использование свойства РежимОтображения. Если вы установите РежимОтображенияЭлементаНастройкиКомпоновкиДанных.БыстрыйДоступ, отбор появится в шапке формы, и пользователь сможет его увидеть. Если же нужно скрыть отбор от пользователя, используйте режим Недоступный.
Если вы хотите, чтобы наложенный программно отбор нельзя было изменить или удалить через настройки списка, следует использовать механизм Фиксированных настроек. Фиксированные настройки суммируются с обычными настройками по правилу «И», но они не видны пользователю в стандартных диалогах настройки.
Выясним, как передать такие настройки при открытии формы:
&НаКлиенте
Процедура ОткрытьСФиксированнымОтбором()
Схема = Новый СхемаКомпоновкиДанных; // Создаем временную схему для формирования настроек
// В реальной задаче лучше подготовить КомпоновщикНастроек заранее
Настройки = Новый НастройкиКомпоновкиДанных;
ГруппаИли = Настройки.Отбор.Элементы.Добавить(Тип("ГруппаЭлементовОтбораКомпоновкиДанных"));
ГруппаИли.ТипГруппы = ТипГруппыЭлементовОтбораКомпоновкиДанных.ГруппаИли;
// Добавляем условия (аналогично предыдущим примерам)
ПараметрыФормы = Новый Структура;
ПараметрыФормы.Вставить("ФиксированныеНастройки", Настройки);
ОткрытьФорму("Справочник.Сотрудники.ФормаВыбора", ПараметрыФормы, ЭтаФорма);
КонецПроцедуры
Этот метод считается более «чистым» с точки зрения архитектуры, так как он не перемешивает программную логику с пользовательскими предпочтениями оформления списка.
Рассмотрим ситуацию, описанную в обсуждении: форма запоминает старые настройки и при следующем открытии отображает некорректные данные. Чтобы избежать этого, можно использовать параметр КлючНазначенияИспользования.
Когда вы открываете форму, платформа сохраняет ее состояние (ширину колонок, отборы) в привязке к ключу. Если при каждом открытии с уникальным набором фильтров вы будете передавать разный ключ (например, «ОтборСотрудниковПоДате»), 1С будет хранить эти настройки отдельно от настроек общего списка. Если же передавать пустую строку или уникальный GUID, форма каждый раз будет открываться в исходном состоянии.
Если ваша конфигурация построена на базе Библиотеки стандартных подсистем (БСП), мы рекомендуем не изобретать велосипед, а использовать готовые программные интерфейсы. Проанализируем возможности общего модуля ОбщегоНазначенияКлиентСервер:
УстановитьЭлементОтбораДинамическогоСписка — позволяет быстро установить простое условие без ручного создания объектов типов.УдалитьЭлементыОтбораДинамическогоСписка — помогает очистить список перед наложением новых условий.Использование функций БСП делает код более читаемым и защищает от ошибок при обновлении платформы, так как типовые механизмы лучше адаптированы под изменения в ядре 1С.
Подводя итог, можно сказать, что наиболее гибким и мощным инструментом для фильтрации данных в 1С остается Компоновщик настроек. Несмотря на его кажущуюся сложность, он позволяет реализовать любые иерархические условия, которые невозможно передать через простую структуру параметров.