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