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