Как настроить отбор банковских счетов по нескольким владельцам в управляемой форме 1С 8.3?

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

В практике разработки на платформе 1С:Предприятие 8.3 часто возникает задача, когда подчиненный справочник должен фильтроваться сразу по нескольким родительским объектам. Типичный пример: в документе выбирается контрагент или связанное с ним физическое лицо, а в поле выбора банковского счета необходимо предоставить пользователю возможность выбрать счета обоих связанных субъектов сразу.

Стандартный механизм метаданных Связи параметров выбора рассчитан только на жесткую фильтрацию по одному конкретному значению реквизита. Попытка объединить условия через логическое «ИЛИ» или передать составной список без доработки интерфейса приводит к тому, что отображаются счета только одного владельца. Разберем детально, как решить эту задачу правильно, какие существуют подходы, их плюсы и скрытые недостатки.

Развеиваем миф: работа стандартного параметра формы «Отбор» с массивами

Среди разработчиков нередко встречается заблуждение, что структура Отбор, передаваемая в параметры открываемой формы, умеет работать исключительно с видом сравнения Равно. На самом деле платформа 1С 8.3 в управляемом интерфейсе проверяет тип переданного значения. Если в структуру параметров формы передать не одиночную ссылку, а массив или список значений, динамический список автоматически установит вид сравнения ВСписке.

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


&НаКлиенте
Процедура БанковскийСчетНачалоВыбора(Элемент, ДанныеВыбора, СтандартнаяОбработка)
    
    СтандартнаяОбработка = Ложь;
    
    МассивВладельцев = ПолучитьМассивВладельцевНаСервере(Объект.Контрагент);
    
    ПараметрыОтбора = Новый Структура;
    ПараметрыОтбора.Вставить("Владелец", МассивВладельцев);
    
    ПараметрыФормы = Новый Структура;
    ПараметрыФормы.Вставить("Отбор", ПараметрыОтбора);
    
    ОткрытьФорму("Справочник.БанковскиеСчета.ФормаВыбора", ПараметрыФормы, Элемент);
    
КонецПроцедуры

В этом случае платформа сама накладывает отбор на стандартный реквизит Владелец динамического списка, и запрос к СУБД строится оптимально по индексированному полю.

Способ 1. Программная установка свойства «ПараметрыВыбора» элемента формы

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

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


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

Разберем преимущества этого способа:

  1. Единообразие интерфейса: отбор применяется не только к модальному или блокирующему окну выбора, но и к быстрому вводу по строке.
  2. Отсутствие дублирования кода: отпадает необходимость переопределять событие НачалоВыбора и писать ручной вызов ОткрытьФорму.
  3. Автоматическое обновление: список счетов в динамическом списке формы выбора всегда остается динамическим и актуальным.

Способ 2. Отбор по предварительно выбранному массиву ссылок счетов

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


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

&НаКлиенте
Процедура БанковскийСчетНачалоВыбора(Элемент, ДанныеВыбора, СтандартнаяОбработка)
    
    СтандартнаяОбработка = Ложь;
    
    СписокСчетов = ПолучитьСписокБанковскихСчетов(Объект.Контрагент);
    
    ПараметрыОтбора = Новый Структура;
    ПараметрыОтбора.Вставить("Ссылка", СписокСчетов);
    
    ПараметрыФормы = Новый Структура;
    ПараметрыФормы.Вставить("Отбор", ПараметрыОтбора);
    
    ОткрытьФорму("Справочник.БанковскиеСчета.ФормаВыбора", ПараметрыФормы, Элемент);
    
КонецПроцедуры

Проанализируем подводные камни данного решения:

  1. Неактуальность на момент создания: если другой пользователь добавит новый банковский счет, пока у текущего пользователя открыта форма документа, этот счет не попадет в выборку без повторного перезапуска запроса.
  2. Нагрузка на СУБД: если счетов много, передача большого списка ссылок в конструкцию Ссылка В (...) менее производительна, чем условие по полю Владелец.
  3. Блокировка интерактивного добавления: при открытии формы с отбором по полю Ссылка кнопка создания нового элемента теряет смысл, так как вновь созданный элемент никогда не удовлетворит условию списка ссылок.

Способ 3. Передача «ФиксированныхНастроек» динамического списка

Если требуется жестко ограничить список выбора так, чтобы пользователь не мог снять установленный фильтр через команду «Настроить список», используем свойство ФиксированныеНастройки. Этот параметр принимает объект НастройкиКомпоновкиДанных:


&НаКлиенте
Процедура ОткрытьФормуВыбораСФиксированнымиНастройками(Элемент)
    
    ФиксированныеНастройки = Новый НастройкиКомпоновкиДанных;
    
    ЭлементОтбора = ФиксированныеНастройки.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
    ЭлементОтбора.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("Владелец");
    ЭлементОтбора.ВидСравнения = ВидСравненияКомпоновкиДанных.ВСписке;
    
    МассивВладельцев = ПолучитьМассивВладельцев(Объект.Контрагент);
    ЭлементОтбора.ПравоеЗначение = МассивВладельцев;
    ЭлементОтбора.Использование = Истина;
    
    ПараметрыФормы = Новый Структура;
    ПараметрыФормы.Вставить("ФиксированныеНастройки", ФиксированныеНастройки);
    
    ОткрытьФорму("Справочник.БанковскиеСчета.ФормаВыбора", ПараметрыФормы, Элемент);
    
КонецПроцедуры

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

Особенность создания новых элементов при отборе по списку владельцев

Обратим внимание на важное поведение платформы 1С: когда в форме выбора подчиненного справочника установлен отбор по одиночному владельцу (вид сравнения Равно), платформа автоматически заполняет реквизит Владелец при нажатии кнопки «Создать». Однако при отборе с видом сравнения ВСписке система не знает, к какому именно из нескольких владельцев привязать новый объект. В результате поле Владелец в карточке нового счета останется пустым, и пользователю потребуется заполнить его вручную.

Если требуется автоматическое заполнение, его реализуют в модуле менеджера или в форме создаваемого объекта, анализируя параметры открытия и контекст сеанса.

← На главную